『TinyOS』学习笔记 #2

本文介绍TinyOS中主动消息(Active Message)层的基础知识及如何使用它进行无线节点间的数据发送与接收。通过实例演示了如何定义消息结构、配置消息类型,并实现简单的无线通信应用程序。

Lesson 3 : Mote-mote radio communication

 

 

Active Message Interfaces

Since it is very common to have multiple services using the same radio to communicate, TinyOS provides the Active Message (AM) layer to multiplex access to the radio. The term "AM type" refers to the field used for multiplexing. AM types are similar in function to the Ethernet frame type field, IP protocol field, and the UDP port in that all of them are used to multiplex access to a communication service. AM packets also includes a destination field, which stores an "AM address" to address packets to particular motes. Additional interfaces, also located in the tos/interfaces directory, were introduced to support the AM services:

 

  • AMPacket - Similar to Packet, provides the basic AM accessors for the message_t abstract data type. This interface provides commands for getting a node's AM address, an AM packet's destination, and an AM packet's type. Commands are also provides for setting an AM packet's destination and type, and checking whether the destination is the local node.
  • AMSend - Similar to Send, provides the basic Active Message sending interface. The key difference between AMSend and Send is that AMSend takes a destination AM address in its send command.

 

The AM address of a node can be set at installation time, using the make install.n or make reinstall.n commands. It can be changed at runtime using the ActiveMessageAddressC component.

 

 

 

Sending a Message over the Radio

 

Reimplementing Blink

BlinkToRadioC.nc

 

 

#include <Timer.h>
 #include "BlinkToRadio.h"
 
 module BlinkToRadioC {
   uses interface Boot;
   uses interface Leds;
   uses interface Timer<TMilli> as Timer0;
 }
 implementation {
   uint16_t counter = 0;
 
   event void Boot.booted() {
     call Timer0.startPeriodic(TIMER_PERIOD_MILLI);
   }
 
   event void Timer0.fired() {
     counter++;
     call Leds.set(counter);
   }
 }

 

 

 

 

BlinkToRadio.h header file

 

#ifndef BLINKTORADIO_H
 #define BLINKTORADIO_H
 
 enum {
   TIMER_PERIOD_MILLI = 250
 };
 
 #endif

 

the use of the ifndef(if not define), define, and endif directives. These directives are used to ensure that the definitions in each header file is not included multiple times because the compiler would complain about multiply-defined objects. By convention, the literal used for these directives is an all-caps version of the filename with any periods converted to underscores.

 

the use of an enum declaration for defining the constant TIMER_PERIOD_MILLI. Using enum for defining constants is preferred over using define because enum does not indiscriminantly replace every occurence of the defined literal, regardless of where it appears in the source. As a result, enums provide better scoping as well.

 

BlinkToRadioAppC.nc (用来连接use interface 和提供了它的实现的组件)to wire the interfaces that the implementation uses to the actual components which provide these interfaces

 

#include <Timer.h>
 #include "BlinkToRadio.h"
 
 configuration BlinkToRadioAppC {
 }
 implementation {
   components MainC;
   components LedsC;
   components BlinkToRadioC as App;
   components new TimerMilliC() as Timer0;
 
   App.Boot -> MainC;
   App.Leds -> LedsC;
   App.Timer0 -> Timer0;
 }

 

 最后建立Makefiel

 

COMPONENT=BlinkToRadioAppC
include $(MAKERULES)

 

The first line tells the TinyOS make system that the top-level application component is BlinkToRadioAppC.

 

The second line loads in the TinyOS build system, which has all of the rules for building and installing on different platforms.

 

 

 

 

Defining a Message Structure

message will send both the node id and the counter value over the radio. Rather than directly writing and reading the payload area of the message_t with this data, we will use a structure to hold them and then use structure assignment to copy the data into the message payload area.

 

用structure来读写payload更便利

Using a structure allows reading and writing the message payload more conveniently when your message has multiple fields or multi-byte fields (like uint16_t or uint32_t) because you can avoid reading and writing bytes from/to the payload using indices and then shifting and adding (e.g. uint16_t x = data[0] << 8 + data[1]).

 

Even for a message with a single field, you should get used to using a structure because if you ever add more fields to your message or move any of the fields around, you will need to manually update all of the payload position indices if you read and write the payload at a byte level. Using structures is straightforward.

 

typedef nx_struct BlinkToRadioMsg {
  nx_uint16_t nodeid;
  nx_uint16_t counter;
} BlinkToRadioMsg;

 

The nx_ prefix is specific to the nesC language and signifies that the struct and uint16_t are external types.

 

External types have the same representation on all platforms. The nesC compiler generates code that transparently reorders access to nx_ data types and eliminates the need to manually address endianness and alignment (extra padding in structs present on some platforms) issues.

 

the nx_ prefix on a type (e.g. nx_uint16_t) indicates the field is to serialized in big endian format. In contrast, the nxle_ prefix signifies that the field is serialized in little endian format.

 

 

 

Sending a Message

 

  1. First, we need to identify the interfaces (and components) that provide access to the radio and allow us to manipulate the message_t type.
  2. Second, we must update the module block in the BlinkToRadioC.nc by adding uses statements for the interfaces we need.
  3. Third, we need to declare new variables and add any initialization and start/stop code that is needed by the interfaces and components.
  4. Fourth, we must add any calls to the component interfaces we need for our application.
  5. Fifth, we need to implement any events specified in the interfaces we plan on using.
  6. Sixth, the implementation block of the application configuration file, BlinkToRadioApp.c, must be updated by adding a components statement for each component we use that provides one of the interfaces we chose earlier.
  7. Finally, we need to wire the interfaces used by the application to the components which provide those interfaces.  

Note using the as keyword to rename an interface. nesC allows interfaces to be renamed in this way for several reasons. First, it often happens that two or more components that are needed in the same module provide the same interface. Second, interfaces are sometimes renamed to something more meaningful.

 

 

components ActiveMessageC;
components new AMSenderC(AM_BLINKTORADIO);

 

ActiveMessageC is a singleton component that is defined once for each type of hardware platform. AMSenderC is a generic, parameterized component. The new keyword indicates that a new instance of AMSenderC will be created. The AM_BLINKTORADIO parameter indicates the AM type of the AMSenderC.  the value of AM_BLINKTORADIO 定义在BlinkToRadio.h header file 中的enum.

 

 

 

Receiving a Message over the Radio

 

 

和上面一样的过程去添加代码。 

 

Note that we can safely manipulate the counter variable outside of an atomic section. The reason is that receive event executes in task context rather than interrupt context (events that have the async keyword can execute in interrupt context). Since the TinyOS execution model allows only one task to execute at a time, if all accesses to a variable occur in task context, then no race conditions will occur for that variable. Since all accesses to counter occur in task context, no critical sections are needed when accessing it.  

 

The AM_BLINKTORADIO parameter indicates the AM type of the AMReceiverC and is chosen to be the same as that used for the AMSenderC used earlier, which ensures that the same AM type is being used for both transmissions and receptions.

 

 

 

 

(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值