要求:
完成节点数据采集和标签信息的远程洪泛传输,在与 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(接收模块) :文章来源:https://www.toymoban.com/news/detail-514174.html
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(数据结构模块):文章来源地址https://www.toymoban.com/news/detail-514174.html
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'
到了这里,关于节点数据采集和标签信息的远程洪泛传输的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!