当前位置:网站首页>节点数据采集和标签信息的远程洪泛传输
节点数据采集和标签信息的远程洪泛传输
2022-06-29 12:58:00 【I_love_hanser_QAQ】
要求:
完成节点数据采集和标签信息的远程洪泛传输,在与 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'
边栏推荐
- How can the sports app keep the end-to-side background alive to make the sports record more complete?
- WinDbg common commands
- 如何让 Dapper 支持 DateOnly 类型
- Introduction to reverse commissioning -pe file section table and block 03/07
- Use Gerrit + Zadig to realize trunk development and trunk publishing (including byte flying Book Practice)
- weserver发布地图服务
- Mondo rescue creates an image file (which is conducive to image damage recovery)
- Autonomous and controllable city! Release of the first domestic artiq architecture quantum computing measurement and control system
- weserver發布地圖服務
- Equivalence class partition method for test case design method
猜你喜欢

Don't build the wheel again. It is recommended to use Google guava open source tool class library. It is really powerful!

二叉树习题总结

Detailed explanation of PDB symbol library files

What if the excel table exported from the repair record is too large?

Hardware development notes (VIII): basic process of hardware development, making a USB to RS232 module (VII): creating a basic dip component (crystal oscillator) package and associating the principle

pdb符号库文件详解

Equivalence class partition method for test case design method

Summary of binary tree exercises

Qitai observation: professional elites must step on the huge pit of entrepreneurship - learning effect pit

电脑时间校对后不自动更新要如何解决
随机推荐
leetcode:226. 翻转二叉树
别再重复造轮子了,推荐使用 Google Guava 开源工具类库,真心强大!
Xiaobai learns MySQL - incremental statistical SQL requirements - windowing function scheme
超 Nice 的表格响应式布局小技巧
Detailed explanation of machine learning out of fold prediction | using out of fold prediction oof to evaluate the generalization performance of models and build integrated models
Why does ETL often become ELT or even let?
Game development of contract quantitative trading system (ready-made case analysis)
College girls wear cheongsam to defend! Netizen: the tutor said it would be nice if the paper were as beautiful as the cheongsam
Getting started with SQLite3
June training (day 29) - divide and rule
Basic type variable declaration
I talked about exception handling for more than half an hour during the interview yesterday
Deecamp2022 officially opened! Likaifu and zhangyaqin personally teach master courses 𞓜 innovation
逆向调试入门-PE文件节表与区块03/07
Hundreds of CVPR people were recruited as new champions. Emoji became a "court witness". M2 MBP was exposed that the hard disk speed was reduced. Today, more big news is here
The node command in the script does not print the execution log on the console
Three best practices help enterprises improve supply chain security
文物数字藏品,开启文化传承的新方式
PG Basics - logical structure management (1)
记一次 .NET 某物管后台服务 卡死分析