读取硬件数据并封装中间件返回JSON

该文展示了如何通过Python和C++实现串口通信读取设备数据,并封装成HTTP服务,以JSON格式返回给客户端。文中提供了Python使用pyserial模块与485设备交互的例子,以及C++调用DLL库进行硬件调用的示例。
摘要由CSDN通过智能技术生成

中间件封装

通过串口读取到设备数据,并将其封装成HTTP服务,供外部调用,返回JSON格式发送回客户端。

import http.server
import json
import serial  # 库pyserial模块


# 通过485通信读取设备值的函数
def read_device_value():
    # 打开串口
    ser = serial.Serial('COM1', 9600, timeout=1)
    # 发送读取指令
    ser.write(b'\x01\x03\x00\x00\x00\x01\x85\xCF')
    # 读取返回值
    result = ser.read(7)
    # 关闭串口
    ser.close()
    # 解析返回值,获取设备数值
    value = int.from_bytes(result[3:5], byteorder='big', signed=False)
    return value


class RequestHandler(http.server.BaseHTTPRequestHandler):
    # 处理HTTP请求的函数
    def do_GET(self):
        # 获取设备值
        value = read_device_value()
        # 封装成JSON
        data = {'value': value}
        json_data = json.dumps(data).encode('utf-8')
        # 构造HTTP响应头
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.send_header('Content-Length', len(json_data))
        self.end_headers()
        # 发送JSON数据包
        self.wfile.write(json_data)


if __name__ == '__main__':
    # 构造HTTP服务器并启动
    server_address = ('', 8080)
    httpd = http.server.HTTPServer(server_address, RequestHandler)
    httpd.serve_forever()

在该示例代码中,read_device_value() 函数实现了通过485通信读取设备当前值的功能,并返回该值。RequestHandler 类继承自 http.server.BaseHTTPRequestHandler ,覆盖了 do_GET() 方法,实现了HTTP GET请求的处理。

在主函数中,创建了一个HTTP服务器对象并启动。当有客户端通过 HTTP GET 请求访问该服务器时,服务器会调用 RequestHandler 中重载的 do_GET() 方法,进而从485设备读取当前值,并将其封装成JSON格式发送回客户端。

使用Python调用485通信的示例代码

import serial

ser = serial.Serial('/dev/ttyS0', 9600, parity=serial.PARITY_NONE,
                    stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1)

if ser.isOpen():
    print("串口已打开")

# 向从机发送数据
data = bytearray([0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xc4, 0x0b])
ser.write(data)

# 读取从机响应
result = ser.read(7)
print(result)

ser.close()

在这个示例中,我们使用Python的serial模块来它打开串口并使用write()方法向从机发送数据。然后,使用read()方法从从机读取响应。

请注意,在此示例中,我们使用的是串口设备文件/dev/ttyS0和波特率为9600。您需要根据您的具体情况更改这些值。此外,也要根据需要设置奇偶校验、停止位和数据位。

此外,根据您的485通信协议,您可能需要修改发送和接收的字节数或解析结果数据。


以下是C++代码示例

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <Windows.h>

// 定义物联网设备的通信端口号
const int PORT_NUM = 485;

// 定义HTTP服务的端口号
const int HTTP_PORT_NUM = 8080;

// 读取物联网设备的数据,并返回JSON数据包
std::string read_device_data() {
    // 通过485通信读取设备数据的代码
    // ...

    // 构造JSON数据包的代码
    std::ostringstream oss;
    oss << "{";
    oss << "\"device_id\": " << device_id << ",";
    oss << "\"data\": {";
    oss << "\"value1\": " << value1 << ",";
    oss << "\"value2\": " << value2;
    oss << "}";
    oss << "}";

    return oss.str();
}

// 处理HTTP请求,并返回JSON数据包
std::string handle_http_request() {
    // 解析HTTP请求的代码
    // ...

    // 调用读取物联网设备数据的函数,获取设备数据
    std::string device_data = read_device_data();

    // 构造HTTP响应的代码
    std::ostringstream oss;
    oss << "HTTP/1.1 200 OK\r\n";
    oss << "Content-Type: application/json\r\n";
    oss << "Content-Length: " << device_data.length() << "\r\n";
    oss << "\r\n";
    oss << device_data;

    return oss.str();
}

// 主函数,启动HTTP服务
int main() {
    // 初始化物联网设备的通信端口
    HANDLE hCom = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    DCB dcb;
    GetCommState(hCom, &dcb);
    dcb.BaudRate = CBR_9600;
    SetCommState(hCom, &dcb);

    // 启动HTTP服务的代码
    SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(HTTP_PORT_NUM);
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(sock, (sockaddr*)&addr, sizeof(addr));
    listen(sock, 10);

    while (true) {
        // 等待HTTP请求的代码
        SOCKET client_sock = accept(sock, NULL, NULL);

        // 处理HTTP请求的代码
        std::string response = handle_http_request();

        // 发送HTTP响应的代码
        send(client_sock, response.c_str(), response.length(), 0);

        closesocket(client_sock);
    }

    closesocket(sock);
    WSACleanup();

    return 0;
}

Python引用DLL库实现硬件调用

以下是一个使用微软Kinect SDK驱动摄像头拍照的Python示例代码:

import ctypes

# 加载Kinect SDK的DLL库
kinect_dll = ctypes.cdll.LoadLibrary("Kinect10.dll")

# 初始化Kinect摄像头
kinect_dll.NuiInitialize(ctypes.c_uint(0))

# 打开摄像头并启用RGB色彩流
kinect_dll.NuiCameraElevationSetAngle(ctypes.c_long(0))
kinect_dll.NuiImageStreamOpen(ctypes.c_ulong(1), ctypes.c_ulong(2),
                              ctypes.c_ulong(0), ctypes.c_ulong(0),
                              ctypes.c_void_p(), ctypes.c_void_p())

# 获取图像信息
image_data = ctypes.create_string_buffer(640 * 480 * 4)
frame_event = kinect_dll.CreateEventW(ctypes.c_void_p(), ctypes.c_bool(True),
                                      ctypes.c_bool(False), ctypes.c_wchar_p(""))
kinect_dll.NuiImageStreamGetNextFrame(ctypes.c_ulong(1), frame_event)

# 将图像信息保存为文件
with open("image.bmp", "wb") as f:
    f.write(image_data.raw)

# 释放资源
kinect_dll.NuiShutdown()

====================================
C++代码实现

#include <iostream>
#include <Windows.h>

// 定义SDK的函数指针类型
typedef int(*InitSerialPortFunc)(int nPort, int nBaudRate, int nDataBits, int nParity, int nStopBits);
typedef int(*CloseSerialPortFunc)();
typedef int(*SendDataFunc)(unsigned char* pData, int nLength);
typedef int(*RecvDataFunc)(unsigned char* pBuffer, int nBufferSize);

// 定义SDK的DLL库名称和函数名
const char* DLL_NAME = "SerialPort.dll";
const char* INIT_SERIAL_PORT_FUNC_NAME = "InitSerialPort";
const char* CLOSE_SERIAL_PORT_FUNC_NAME = "CloseSerialPort";
const char* SEND_DATA_FUNC_NAME = "SendData";
const char* RECV_DATA_FUNC_NAME = "RecvData";

// 定义物联网设备的通信端口号和波特率
const int PORT_NUM = 1;
const int BAUD_RATE = 9600;

// 初始化SDK,加载DLL库和函数指针
bool init_sdk(HINSTANCE& hDll, InitSerialPortFunc& init_func, CloseSerialPortFunc& close_func, SendDataFunc& send_func, RecvDataFunc& recv_func) {
    // 加载DLL库
    hDll = LoadLibraryA(DLL_NAME);
    if (hDll == NULL) {
        std::cerr << "Failed to load DLL library " << DLL_NAME << std::endl;
        return false;
    }

    // 获取函数指针
    init_func = (InitSerialPortFunc)GetProcAddress(hDll, INIT_SERIAL_PORT_FUNC_NAME);
    close_func = (CloseSerialPortFunc)GetProcAddress(hDll, CLOSE_SERIAL_PORT_FUNC_NAME);
    send_func = (SendDataFunc)GetProcAddress(hDll, SEND_DATA_FUNC_NAME);
    recv_func = (RecvDataFunc)GetProcAddress(hDll, RECV_DATA_FUNC_NAME);

    if (init_func == NULL || close_func == NULL || send_func == NULL || recv_func == NULL) {
        std::cerr << "Failed to get function pointers from DLL library " << DLL_NAME << std::endl;
        return false;
    }

    // 初始化串口通信
    int ret = init_func(PORT_NUM, BAUD_RATE, 8, 0, 1);
    if (ret != 0) {
        std::cerr << "Failed to initialize serial port" << std::endl;
        return false;
    }

    return true;
}

// 发送数据到物联网设备
bool send_data_to_device(unsigned char* data, int length, SendDataFunc send_func) {
    // 调用SDK的发送数据函数
    int ret = send_func(data, length);
    if (ret != 0) {
        std::cerr << "Failed to send data to device" << std::endl;
        return false;
    }

    return true;
}

// 从物联网设备接收数据
bool recv_data_from_device(unsigned char* buffer, int buffer_size, RecvDataFunc recv_func) {
    // 调用SDK的接收数据函数
    int ret = recv_func(buffer, buffer_size);
    if (ret <= 0) {
        std::cerr << "Failed to receive data from device" << std::endl;
        return false;
    }

    return true;
}

// 关闭SDK,释放资源
void close_sdk(HINSTANCE hDll, CloseSerialPortFunc close_func) {
    // 关闭
int ret = close_func();
if (ret != 0) {
    std::cerr << "Failed to close serial port" << std::endl;
}

// 卸载DLL库
FreeLibrary(hDll);
}

// 主函数,演示如何使用SDK进行485通信
int main() {
// 初始化SDK
HINSTANCE hDll;
InitSerialPortFunc init_func;
CloseSerialPortFunc close_func;
SendDataFunc send_func;
RecvDataFunc recv_func;
if (!init_sdk(hDll, init_func, close_func, send_func, recv_func)) {
return 1;
}

// 发送数据到物联网设备
unsigned char data[] = { 0x01, 0x02, 0x03 };
int length = sizeof(data) / sizeof(unsigned char);
if (!send_data_to_device(data, length, send_func)) {
    close_sdk(hDll, close_func);
    return 1;
}

// 从物联网设备接收数据
unsigned char buffer[1024];
int buffer_size = sizeof(buffer) / sizeof(unsigned char);
if (!recv_data_from_device(buffer, buffer_size, recv_func)) {
    close_sdk(hDll, close_func);
    return 1;
}

// 处理接收到的数据
// ...

// 关闭SDK,释放资源
close_sdk(hDll, close_func);

return 0;
}

请注意,以上代码仅供参考,你需要根据你的具体需求和SDK的API做出适当的修改和调整。同时,还需要确保你已经获取到了SDK的DLL库和函数指针,并且了解了正确的数据格式和传输协议。

注意:上述示例代码仅供参考,具体编写时需要根据具体的SDK和设备接口进行调整。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值