远程洪泛传输中的节点数据采集和标签信息

要求:

        完成节点数据采集和标签信息的远程洪泛传输,在与 Sink 节点相连接的 PC
上能看到结果(标签信息、感知的数据)。其中,节点感知数据采集包括光照值、温湿度值,采集节点每 20s
采集一次温湿度、每10s 采集一次光照。标签数据读写控制周期自行决定。

注:下面只贴出关键代码,完整程序代码详见我的资源……

        读卡器节点会周期性地读取温湿度,光照,标签数据并通过洪泛广播的形式发给Sink节点,Sink节点与PC机相联,Sink接收到数据包后上传至串口,PC机上的Python程序对串口数据进行处理并显示在UI界面上。

运行效果截图(Python语言) :


配置组件代码: 

includes Adhoc_APP;

configuration Adhoc_APP { }
implementation
{
  components MainC, Adhoc_APPM
           	, new TimerMilliC() as Timer1, new TimerMilliC() as Timer2,new TimerMilliC() as Timer3,new TimerMilliC() as Timer4
          	, LedsC
           	, FloodingC as Route
	   		, BusyWaitMicroC
     		, RFID_ControlC;

  	Adhoc_APPM.RFID_Control -> RFID_ControlC;

  	Adhoc_APPM.Boot -> MainC; // 初始化组件
  	Adhoc_APPM.Leds -> LedsC; // Led灯控制组件
  	Adhoc_APPM.Timer1 -> Timer1; // 定时器控制组件
  	Adhoc_APPM.Timer2 -> Timer2; // 定时器控制组件
  	Adhoc_APPM.Timer3 -> Timer3; // 定时器控制组件
  	Adhoc_APPM.Timer4 -> Timer4; 
  	Adhoc_APPM.BusyWait ->BusyWaitMicroC;

  	Adhoc_APPM.RControl	-> Route;
  	Adhoc_APPM.Rout_Send  -> Route;
  	Adhoc_APPM.Rout_Receive -> Route;

  	// Sensors Components
  	components new SensirionSht11C(), new PhotoSensorC();
  	Adhoc_APPM.Read_Humi -> SensirionSht11C.Humidity;
  	Adhoc_APPM.Read_Temp -> SensirionSht11C.Temperature;
  	Adhoc_APPM.Read_Photo -> PhotoSensorC;

  	// Uart Components
  	components SCSuartDBGC;
  	components ActiveMessageC;
  	Adhoc_APPM.CommControl -> ActiveMessageC;
  	Adhoc_APPM.SCSuartSTD -> SCSuartDBGC;
  	Adhoc_APPM.SCSuartDBG -> SCSuartDBGC;
}

模块组件代码: 

module Adhoc_APPM {
	uses {
    	interface Boot;
    	interface Timer<TMilli> as Timer1;
		interface Timer<TMilli> as Timer2;
		interface Timer<TMilli> as Timer3;
		interface Timer<TMilli> as Timer4;
    	interface Leds;
    	interface BusyWait<TMicro, uint16_t>;
		interface RFID_Control;
    	interface StdControl as RControl;
    	interface AMSend as Rout_Send;
    	interface Receive as Rout_Receive;
		interface SplitControl as CommControl;
  	}

  	// Sensor components
  	uses {
		interface Read<uint16_t> as Read_Humi;
		interface Read<uint16_t> as Read_Temp;
		interface Read<uint16_t> as Read_Photo;
  	}

  	// Uart component
  	uses {
		interface StdControl as SCSuartSTD;
		interface SCSuartDBG;
  	}

}
implementation {

  	message_t TXData;

  	 sensor data 
  	uint16_t myTemp=0xFFFF;
  	uint16_t myHumi=0xFFFF;
  	uint16_t myPhoto=0xFFFF;
  	uint16_t Raw_Temp=0xFFFF; // Raw temp info
  	uint8_t FUN = 0x00;
  	uint8_t Data[5] = {0x00,0x00,0x00,0x00,0x00,};
  	
	//   uint8_t OutputUartMsg[64]; // 串口输出消息buff
  	void calc_SHT_(uint16_t p_humidity ,uint16_t p_temperature);


  	event void Boot.booted() {
	    uint8_t mote_id = (uint8_t) TOS_NODE_ID;
		if (TOS_NODE_ID != Sink_Addr) // 不是sink节点
		{ 
			call Timer3.startOneShot(1000);
	    	call Timer1.startPeriodic(SHT_Interval);  // 每隔20s读取一次温湿度数据
			call Timer4.startPeriodic(3000); // 每隔7s读取一次标签
		} 
		call RControl.start(); 
    	call CommControl.start(); 
  	}

  	event void CommControl.startDone(error_t error) {
    	call SCSuartSTD.start();
    	call RFID_Control.start();
  	}

  	event void CommControl.stopDone(error_t error) {}

  	event void Timer3.fired() {
		call Timer2.startPeriodic(light_Interval); // 每隔10s读取一次光照数据
  	}
  	// get sensor data as photo, temp., humi.
  	// 定时器溢出读取光照数据
  	event void Timer2.fired() {
    	call Leds.led2Toggle();
    	call Read_Photo.read(); 
  	}
  	// 定时器溢出读取温湿度
  	event void Timer1.fired() {
		call Leds.led2Toggle();
		call Read_Temp.read();
  	}

  	// 一般节点发送给Sink节点采集到的数据
  	task void transmit_frame(){
  
	  	DataFrameStruct DFS;
	
	  	call Leds.led1On();
	
	  	DFS.Temp	= myTemp;
	  	DFS.Humi	= myHumi;
	  	DFS.Photo	= myPhoto;
	  	atomic DFS.FUN = FUN;
	  	// memcpy (DFS.ID, ID, sizeof(ID));
		memcpy (DFS.Data, Data, sizeof(Data));
	  	memcpy (call Rout_Send.getPayload(&TXData), &DFS, sizeof(DataFrameStruct));

	  	call Rout_Send.send(Sink_Addr, &TXData, sizeof(DataFrameStruct));
  	}

  	// 一般节点数据发送完成事件
  	event void Rout_Send.sendDone(message_t* m, error_t err) {
    	if (err == SUCCESS)
	    	call Leds.led1Off();
  	}

  	// sink节点接收到一般节点发送的数据事件
	event message_t* Rout_Receive.receive(message_t* msg, void* payload, uint8_t len) {
    	if (TOS_NODE_ID == Sink_Addr) 
    	{
	    	uint8_t UART_Buff[65], *UART_Buff_p;
	    	uint8_t UART_Buff_len = 0, i;
	    	Route_Msg NWKF;
	    	DataFrameStruct DFS;
	    	UartFrameStruct UFS; 

	    	memcpy(&NWKF,  call Rout_Send.getPayload(msg), sizeof(Route_Msg));
	    	memcpy(&DFS, NWKF.AppData, sizeof(DataFrameStruct));
	    	UART_Buff_p = (uint8_t *)&UFS;

	    	{
		    	uint32_t Packet_Seq = (uint32_t) NWKF.Sequence;
		    	int16_t OrigiSrcAddr = NWKF.OrigiSrcAddr;
		    	//call SCSuartDBG.UARTSend(UART_Buff, 6);

		    	memcpy (UART_Buff_p+6, (void *)&OrigiSrcAddr, 2);
		    	memcpy (UART_Buff_p+8, (void *)&TOS_NODE_ID, 2);
		    	memcpy (UART_Buff_p+10, (void *)&NWKF.Dst2_for_multihop, 2);
		  		memcpy (UART_Buff_p+12,(void *)&NWKF.Dst3_for_multihop, 2);
		  		memcpy (UART_Buff_p+14,(void *)&Packet_Seq, 4);
		  		memcpy (UART_Buff_p+18,(void *)&DFS.Temp, 2);
		  		memcpy (UART_Buff_p+20,(void *)&DFS.Humi, 2);
		  		memcpy (UART_Buff_p+22,(void *)&DFS.Photo, 2);
		  		memcpy (UART_Buff_p+24,(void *)&DFS.FUN, 1);
				// memcpy (UART_Buff_p+25,(void *)&DFS.ID, 8);
		 		memcpy (UART_Buff_p+25,(void *)&DFS.Data, 5);
	    	}
	    	UART_Buff_len = 0;
	    	for ( i=6; i<sizeof(UartFrameStruct) ; i++)
	    	{
				UART_Buff[UART_Buff_len++] = UART_Buff_p[i];
	    	}
			// call SCSuartDBG.UARTSend(DFS.Data, sizeof(DFS.Data));
        	// 串口数据发送
	    	call SCSuartDBG.UARTSend(UART_Buff, UART_Buff_len -13);
	
	    	call Leds.led0Toggle();
    	}
    	return msg;
	}

  	// 读取光照完成事件,发送数据至sink节点
  	event void Read_Photo.readDone(error_t err, uint16_t val) {
	if (err == SUCCESS)
		{
			myPhoto = val;
			atomic FUN = 1;
		}
		post transmit_frame();
  	}  

  	// 读取温度完成事件,准备读取湿度
  	event void Read_Temp.readDone(error_t err, uint16_t val) {
		if (err == SUCCESS)
			Raw_Temp = val;
		call Read_Humi.read();
  	} 
  
  	// 读取湿度完成事件,发送数据至sink节点
  	event void Read_Humi.readDone(error_t err, uint16_t val) {
		if (err == SUCCESS && Raw_Temp!=0xFFFF)
		{
			calc_SHT_(val, Raw_Temp);
			atomic FUN = 2;
		}
		post transmit_frame();
  	} 

  // 对温湿度循环冗余,得到真实数值
  	void calc_SHT_(uint16_t p_humidity ,uint16_t p_temperature)
  	//----------------------------------------------------------------------------------------
  	// calculates temperature [C] and humidity [%RH]
  	// input : humi [Ticks] (12 bit)
  	// temp [Ticks] (14 bit)
  	// output: humi [%RH]
  	// temp [C]
  	{ 
		const float C1=-4.0; // for 12 Bit
		const float C2= 0.0405; // for 12 Bit
		const float C3=-0.0000028; // for 12 Bit
		const float T_1=0.01; // for 14 Bit @ 5V
		const float T_2=0.00008; // for 14 Bit @ 5V
 
		float rh_lin; // rh_lin: Humidity linear
		float rh_true; // rh_true: Temperature compensated humidity
		float t_C; // t_C : Temperature [C]
		float rh=(float)p_humidity; // rh: Humidity [Ticks] 12 Bit
		float t=(float)p_temperature; // t: Temperature [Ticks] 14 Bit
    
		t_C=t*0.01 - 40; //calc. Temperature from ticks to [C]
		rh_lin=C3*rh*rh + C2*rh + C1; //calc. Humidity from ticks to [%RH]
		rh_true=(t_C-25)*(T_1+T_2*rh)+rh_lin; //calc. Temperature compensated humidity [%RH]
		if(rh_true>100)rh_true=100; //cut if the value is outside of
		if(rh_true<0.1)rh_true=0.1; //the physical possible range
		atomic myTemp=(uint16_t)t_C; //return temperature [C]
		atomic myHumi=(uint16_t)rh_true; //return humidity[%RH]
  	}
  	//
  	// 获取15693ID完成后发送至Sink节点
	async event void RFID_Control.GetID_15693_Done (char status, uint8_t *buff, char size){
    	// memcpy(ID, buff, 8);
		// atomic FUN = 3;
		// post transmit_frame();
	 	// call RFID_Control.RData_15693(block);
	}
	// 获取15693标签数据完成后发送至Sink节点
	async event void RFID_Control.RData_15693_Done (char status, uint8_t *buff, char size){
      	call SCSuartDBG.UARTSend(buff, 5);
	  	memcpy(Data, buff, 5);
		atomic FUN = 3;
    	post transmit_frame();
  	}
	// 读取标签数据定时器
  	event void Timer4.fired() {
	  	call RFID_Control.RData_15693 (5); 
  	}

	async event void RFID_Control.GetID_14443A_Done(char status, uint8_t *buff, char size) {}
	async event void RFID_Control.WData_15693_Done(char status){}
}

Python程序代码: 

Server.py(主程序):

from PySide2.QtCore import QFile    # 导入文件类
from PySide2.QtWidgets import QApplication  # 导入QtWidgets模块
from PySide2.QtUiTools import QUiLoader  # 加载UI文件
import threading  # 线程模块
import serial  # 导入串口模块
from Receive import *  # 导入接收数据模块(用户)

# 配置串口
portx = "COM3"
bps = 57600
# 超时设置,None:永远等待操作,0为立即返回请求结果,其他值为等待超时时间(单位为秒)
timex = None
ser = serial.Serial(portx, bps, timeout=timex)  # 开启串口通信


class Software:

    def __init__(self):
        # 从文件中加载UI定义
        qfile_Server = QFile("UI/software.ui")
        qfile_Server.open(QFile.ReadOnly)
        qfile_Server.close()
        # 从 UI 定义中动态 创建一个相应的窗口对象
        self.ui = QUiLoader().load(qfile_Server)
        # 按钮绑定事件
        self.ui.openButton.clicked.connect(self.open)
        self.ui.closeButton.clicked.connect(self.close)
        self.ui.ClearButton.clicked.connect(self.clear)

    def open(self):  # 开机
        self.ui.openButton.setEnabled(False)
        self.ui.closeButton.setEnabled(True)
        self.ui.ClearButton.setEnabled(True)

    def close(self):  # 关机
        self.ui.openButton.setEnabled(True)
        self.ui.closeButton.setEnabled(False)
        self.ui.ClearButton.setEnabled(False)
        self.ui.Tempture.setText("")
        self.ui.Humi.setText("")
        self.ui.Photo.setText("")
        self.ui.Data.setText("")
        self.ui.Frame.clear()

    def clear(self):  # 清空文本浏览框
        self.ui.Frame.clear()


# 实例化窗口程序
app = QApplication([])
software = Software()
software.ui.show()
# 设置接受数据守护线程
receivethread = threading.Thread(
    target=lambda: receive(software, ser))
receivethread.setDaemon(True)
receivethread.start()
# 循环执行
app.exec_()

Receive.py(接收模块) :

from AttributeStruct import *  # 数据结构模块(用户)
import struct  # 字节流解封装模块


def receive(software, ser):  # 接收线程
    while(True):
        if software.ui.closeButton.isEnabled():  # 如果已经开机
            Frame = ser.read(24)    # 接收24B数据
            # 保留接收到的数据帧有效字段
            Attributes_set(Frame[0], Frame[2], Frame[8], Frame[12], Frame[14],
                           Frame[16:18], Frame[18], Frame[19], Frame[20:])
            # 处理接收到的数据帧数据
            Attributes['Photo'] = struct.unpack('H', Attributes['Photo'])[0]
            Attributes['FrameType'] = FrameType_rename(Attributes['FrameType'])
            Attributes['CardData'] = CardData_to_string(Attributes['CardData'])
            # 更新UI界面
            updateUI(software, Attributes)


def updateUI(software, Attributes):  # 更新UI界面
    software.ui.Tempture.setText(str(Attributes['tempture']))   # 更新温度
    software.ui.Humi.setText(str(Attributes['Humi']))   # 更新湿度
    software.ui.Photo.setText(str(Attributes['Photo']))  # 更新光照
    # 更新文本浏览框
    if str(Attributes['CardData']) != 'None':   # 未读取到标签数据
        software.ui.Data.setText('   ' + str(Attributes['CardData']))
    else:   # 读到标签数据
        software.ui.Data.setText('')
    software.ui.Frame.append('OrigiSrcAddr:' + str(Attributes['OrigiSrcAddr']) + ';DestAddr:' + str(
        Attributes['DestAddr']) + ';Seq:' + str(Attributes['Seq']))
    software.ui.Frame.ensureCursorVisible()

    if str(Attributes['FrameType']) == '读取光照数据':
        software.ui.Frame.append(
            'Photo:' + str(Attributes['Photo']) + 'LX; FrameType:' + str(Attributes['FrameType']))
    elif str(Attributes['FrameType']) == '读取温湿度数据':
        software.ui.Frame.append('Tempture:' + str(Attributes['tempture']) + '℃; Humi:' + str(Attributes['Humi']) + '%rh;'
                                 + 'FrameType:' + str(Attributes['FrameType']))
    elif str(Attributes['FrameType']) == '读取标签信息':
        software.ui.Frame.append('CardData:' + str(Attributes['CardData'])
                                 + ';FrameType:' + str(Attributes['FrameType']))
    software.ui.Frame.ensureCursorVisible()

AttributesStruct.py(数据结构模块):

import struct  # 字节流解封装模块
# 接收数据结构
Attributes = {
    'OrigiSrcAddr': 0x00,   # 源地址(读卡器地址)
    'DestAddr': 0x00,   # 目的地址(sink地址)
    'Seq': 0x00,    # 数据包的序列号
    'tempture': 0xFF,   # 温度数据
    'Humi': 0xFF,   # 湿度数据
    'Photo': b'\xFF\xFF',   # 光照数据
    'Error': 0x00,  # 读取标签是否成功 (0:成功, 2:失败)
    'CardData': b'\xFF\xFF\xFF\xFF',    # 标签信息
    'FrameType': 0x00,  # 数据帧类型(1:光照,2:温湿度,3:标签信息)
}


def Attributes_set(OrigiSrcAddr, DestAddr, Seq, tempture, Humi, Photo, FrameType, Error, CardData):  # 更新数据结构
    Attributes['OrigiSrcAddr'] = OrigiSrcAddr
    Attributes['DestAddr'] = DestAddr
    Attributes['Seq'] = Seq
    Attributes['tempture'] = tempture
    Attributes['Humi'] = Humi
    Attributes['Photo'] = Photo
    Attributes['FrameType'] = FrameType
    Attributes['Error'] = Error
    Attributes['CardData'] = CardData
    return Attributes


def FrameType_rename(FrameType):  # 数据帧种类
    if FrameType == 1:
        return '读取光照数据'
    elif FrameType == 2:
        return '读取温湿度数据'
    elif FrameType == 3:
        return '读取标签信息'


def CardData_to_string(CardData):  # 将标签数据转换为字符串(字节流转化为整数)
    CardData = struct.unpack('4B', CardData)
    if (Attributes['Error'] == 0):  # 如果读取标签成功
        string = ""
        for i in range(0, len(CardData)):
            if CardData[i] > 9:
                string += str(chr(CardData[i])) + ' '
            else:
                string += str(CardData[i]) + ' '
        return string
    else:   # 读取标签数据失败
        return 'None'
物联沃分享整理
物联沃-IOTWORD物联网 » 远程洪泛传输中的节点数据采集和标签信息

发表评论