虽然FsuOS的驱动分为4大类,但是不同类型间还是有共同的部分
代码的组织,一般分为3个文件:
#ifndef XXXX_INTERFACE_H
#define XXXX_INTERFACE_H
#include "common_interface.h"
#pragma pack(push)
#pragma pack(1)
struct XXXX_Data_t {
unsigned int data_id;
/*uint8_t value;
数据成员定义 */
tele_c_time update_time;
};
#pragma pack(pop)
#endif
这里面要注意的是XXXX_Data_t这个结构体,最开始是个data_id,这个是网页创建设备时候生成的唯一ID,tele_c_time 是本次数据的保存时间。
#ifndef XXXX_H
#define XXXX_H
#include "SMDDIDevice.hpp"
#include "XXXX_interface.h"
#include "UniDataDevice.h"
#define RT_XXXX 5043
class XXXX: public UniDataDevice<XXXX_Data_t, SMDDIDevice, RT_XXXX>
{
public:
XXXX();
bool InitSetting(const Json::Value &settingRoot) override;
bool process(char di, bool first_time);
void RunCheckThreshold() override;
int DeviceIoControl(int ioControlCode, const void* inBuffer, int inBufferSize, void* outBuffer, int outBufferSize, int& bytesReturned) override;
};
PLUMA_INHERIT_PROVIDER(XXXX, SMDDIDevice);
#endif
根据本设备的分类,开始要选择include SMDDIDevice.hpp/SMDAIDevice.hpp/SMDSPDevice.hpp/SMDSocketDevice中的一个。
然后include第一步的XXXX_interface.h
然后include我们的模板类"UniDataDevice.h",UniDataDevice.h是封装了很多重复的代码,大家可以读这个代码了解里面是如何工作的。
定义RT_XXXX,这个当有程序使用SC的C接口接收到XXXX_Data_t的数据时,来区分是哪个型号的设备数据,平时没有用到的地方。
然后从UniDataDevice继承。
PLUMA_INHERIT_PROVIDER声明XXXX为SMDDIDevice的设备。
下面的4个函数都是我们最常用的:
#include "XXXX.h"
#include "UniDataDevice.cpp"
XXXX::XXXX()
{
device_type_ = "xxxx";
}
bool XXXX::InitSetting(const Json::Value &settingRoot)
{
cData.data_id = data_id_;
if(settingRoot["appSetting"] != Json::nullValue &&
settingRoot["appSetting"].type() == Json::objectValue) {
if(settingRoot["appSetting"]["xx"] != Json::nullValue) {
xx_ = settingRoot["appSetting"]["xx"].asInt();
}
}
return UniDataDevice<XXXX_Data_t, SMDDIDevice, RT_XXXX>::InitSetting(settingRoot);
}
bool XXXX::process(char di, bool first_time)
{
//进行处理,处理完成后,调用RoundDone进行告警判断和数据保存
RoundDone();
return true;//false
}
void XXXX::RunCheckThreshold()
{
}
int XXXX::DeviceIoControl(int ioControlCode, const void* inBuffer, int inBufferSize, void* outBuffer, int outBufferSize, int& bytesReturned)
{
}
#ifdef USE_SEPERATE_DRIVER
extern "C"
std::vector<std::shared_ptr<Provider>> get_providers()
{
std::vector<std::shared_ptr<Provider>> providerVec;
providerVec.push_back(std::make_shared<XXXXProvider>());
return std::move(providerVec);
}
#endif
驱动中常用函数: 在驱动中,有一些常用函数:
具体参考 SMDVDevice.h 文件
DeviceIoControl 的返回值
= 0 的值都是驱动返回的,以前比较乱,我们不考虑错误的情况,只要>=0都认为是对的
实际可以细分为:
0 代表设备执行命令成功
0 个别设备执行出问题,返回了错误代码
< 0 代表 SMDDevice调用驱动有问题,没找到设备的可能大,一般返回-1 代表调用设备后,获取执行结果超时,原因主要是设备通信异常,命令错导致不返回
-3 代表没有这个设备
-5 代表有这个设备,但是没有加载驱动,即没有驱动支持命令