Code Review for Alarm

This commit is contained in:
cdyong 2016-11-08 04:11:57 +00:00
parent 4cb3c8ebe8
commit 8eafac4b73
3 changed files with 107 additions and 140 deletions

View File

@ -5,31 +5,21 @@
class AlarmConfig :public ConfigBase class AlarmConfig :public ConfigBase
{ {
public: public:
byte Length; byte Count;
AlarmDataType Data[20]; AlarmItem Items[20];
byte TagEnd; byte TagEnd;
AlarmConfig(); AlarmConfig();
virtual void Init();
}; };
AlarmConfig::AlarmConfig() AlarmConfig::AlarmConfig()
{ {
_Name = "AlarmCf"; _Name = "AlarmCf";
_Start = &Length; _Start = &Count;
_End = &TagEnd; _End = &TagEnd;
Init(); Init();
} }
void AlarmConfig::Init()
{
Buffer(Data, sizeof(Data)).Clear();
for (int i = 0; i < ArrayLength(Data); i++)
{
Data[i].Number = i + 1;
}
}
/************************************************/ /************************************************/
Alarm::Alarm() Alarm::Alarm()
@ -37,138 +27,113 @@ Alarm::Alarm()
AlarmTaskId = 0; AlarmTaskId = 0;
} }
bool Alarm::AlarmSet(const Pair& args, Stream& result) bool Alarm::Set(const Pair& args, Stream& result)
{ {
debug_printf("AlarmSet\r\n"); debug_printf("Set\r\n");
AlarmDataType alarm;
alarm.Enable = false;
Buffer buf = args.Get("alarm"); Buffer buf = args.Get("alarm");
if (buf.Length() < 7 || buf[0] > 20)
Stream ms(buf);
if (buf.Length() < 7)
{ {
debug_printf("数据有误\r\n"); debug_printf("数据有误\r\n");
result.Write((byte)0); result.Write((byte)0);
return false; return false;
} }
byte Id = 0xff; auto& item = *(AlarmItem*)buf.GetBuffer();
Id = ms.ReadByte();
if (Id > 20)
{
debug_printf("Index有误\r\n");
result.Write((byte)0);
return false;
}
alarm.Number = Id;
alarm.Enable = ms.ReadByte(); if (item.Hour > 23 && item.Hour != 0xFF || item.Minutes > 59 || item.Seconds > 59) return false;
byte type = ms.ReadByte(); debug_printf("%d %d %d 执行 bs", item.Hour, item.Minutes, item.Seconds);
alarm.Type.Init(type);
alarm.Hour = ms.ReadByte(); byte resid = SetCfg(item);
alarm.Minutes = ms.ReadByte(); result.Write(resid);
alarm.Seconds = ms.ReadByte();
if (alarm.Hour > 23 || alarm.Minutes > 59 || alarm.Seconds > 59)return false; return resid;
// Buffer buf2(data.Data, sizeof(data.Data));
// auto len = ms.ReadArray(buf2);
Buffer buf2(alarm.Data, sizeof(alarm.Data));
Buffer buf3(buf.GetBuffer() + ms.Position(), buf.Length() - ms.Position());
buf2 = buf3;
// buf.Show(true);
// buf3.Show(true);
debug_printf("%d %d %d 执行 bs", alarm.Hour, alarm.Minutes, alarm.Seconds);
buf2.Show(true);
byte resid = SetCfg(Id, alarm);
result.Write((byte)resid);
if (resid)return true;
return false;
} }
bool Alarm::AlarmGet(const Pair& args, Stream& result) bool Alarm::Get(const Pair& args, Stream& result) const
{ {
// debug_printf("AlarmGet");
AlarmConfig cfg; AlarmConfig cfg;
cfg.Load(); cfg.Load();
// debug_printf("data :\r\n");
result.Write((byte)20); // 写入长度 result.Write(cfg.Count);
for (int i = 0; i < 20; i++) // ZhuYi BuLianXu
for (int i = 0; i < ArrayLength(cfg.Items); i++)
{ {
Buffer bs(&cfg.Data[i].Number, sizeof(AlarmDataType)); auto& item = cfg.Items[i];
bs.Show(true); if(item.Index > 0)
result.WriteArray(bs); {
result.WriteArray(Buffer(&item, sizeof(item)));
}
} }
Buffer(result.GetBuffer(), result.Position()).Show(true);
// debug_printf("\r\n");
return true; return true;
} }
byte Alarm::SetCfg(byte id, AlarmDataType& data) byte Alarm::SetCfg(const AlarmItem& item)
{ {
AlarmConfig cfg; AlarmConfig cfg;
cfg.Load(); cfg.Load();
byte id = item.Index;
if (!id) // 找到空闲位置 if (!id) // 找到空闲位置
{ {
for (int i = 0; i < 20; i++) for (int i = 0; i < ArrayLength(cfg.Items); i++)
{ {
if (!cfg.Data[i].Enable) if (cfg.Items[i].Index == 0)
{ {
id = i + 1; id = i + 1;
break; break;
} }
} }
} }
if (!id)return 0; // 查找失败 if (!id) return 0; // 查找失败
Buffer bf(&data.Number, sizeof(AlarmDataType)); if(item.Hour < 0xFF)
Buffer bf2(&cfg.Data[id - 1].Number, sizeof(AlarmDataType)); Buffer::Copy(&cfg.Items[id - 1], &item, sizeof(item));
bf2 = bf; else // Delete
cfg.Items[id - 1].Index = 0;
for (int i = 0; i < 20; i++) int n = 0;
for (int i = 0; i < ArrayLength(cfg.Items); i++)
{ {
cfg.Data[i].Number = i + 1; // 避免 id 出错 if(cfg.Items[i].Index > 0) n++;
} }
cfg.Count = n;
cfg.Save(); cfg.Save();
// 修改过后要检查一下Task的时间 // 取消下次动作并重新计算 // 修改过后要检查一下Task的时间 // 取消下次动作并重新计算
NextAlarmIds.Clear(); NextAlarmIds.Clear();
Start(); Start();
return id; return id;
} }
bool Alarm::GetCfg(byte id, AlarmDataType& data) bool Alarm::GetCfg(byte id, AlarmItem& item)
{ {
AlarmConfig cfg; AlarmConfig cfg;
cfg.Load(); cfg.Load();
Buffer bf(&data.Number, sizeof(AlarmDataType)); Buffer bf(&item.Index, sizeof(AlarmItem));
Buffer bf2(&cfg.Data[id].Number, sizeof(AlarmDataType)); Buffer bf2(&cfg.Items[id].Index, sizeof(AlarmItem));
bf = bf2; bf = bf2;
return true; return true;
} }
int Alarm::CalcNextTime(AlarmDataType& data) int Alarm::CalcNextTime(AlarmItem& item)
{ {
debug_printf("CalcNextTime Id %d ",data.Number); debug_printf("CalcNextTime Id %d ",item.Index);
auto now = DateTime::Now(); auto now = DateTime::Now();
byte type = data.Type.ToByte(); byte type = item.Type.ToByte();
byte week = now.DayOfWeek(); byte week = now.DayOfWeek();
int time; int time;
if (type & 1 << week) // 今天 if (type & 1 << week) // 今天
{ {
DateTime dt(now.Year, now.Month, now.Day); DateTime dt(now.Year, now.Month, now.Day);
dt.Hour = data.Hour; dt.Hour = item.Hour;
dt.Minute = data.Minutes; dt.Minute = item.Minutes;
dt.Second = data.Seconds; dt.Second = item.Seconds;
if (dt > now) if (dt > now)
{ {
time = (dt - now).Ms; time = (dt - now).Ms;
@ -199,12 +164,12 @@ byte Alarm::FindNext(int& nextTime)
int miniTime = Int_Max; int miniTime = Int_Max;
int tomorrowTime = ToTomorrow(); int tomorrowTime = ToTomorrow();
int times[ArrayLength(cfg.Data)]; int times[ArrayLength(cfg.Items)];
for (int i = 0; i < ArrayLength(cfg.Data); i++) for (int i = 0; i < ArrayLength(cfg.Items); i++)
{ {
times[i] = Int_Max; times[i] = Int_Max;
if (!cfg.Data[i].Enable)continue; if (!cfg.Items[i].Enable)continue;
int time = CalcNextTime(cfg.Data[i]); // 但凡有效的都计算出来 int time = CalcNextTime(cfg.Items[i]); // 但凡有效的都计算出来
times[i] = time; times[i] = time;
if (time < miniTime)miniTime = time; // 找出最小时间 if (time < miniTime)miniTime = time; // 找出最小时间
@ -213,7 +178,7 @@ byte Alarm::FindNext(int& nextTime)
NextAlarmIds.Clear(); NextAlarmIds.Clear();
if (miniTime != Int_Max) if (miniTime != Int_Max)
{ {
for (int i = 0; i < ArrayLength(cfg.Data); i++) for (int i = 0; i < ArrayLength(cfg.Items); i++)
{ {
if (times[i] == miniTime) if (times[i] == miniTime)
{ {
@ -237,18 +202,18 @@ byte Alarm::FindNext(int& nextTime)
void Alarm::AlarmTask() void Alarm::AlarmTask()
{ {
// 获取定时的数据 // 获取定时的数据
AlarmDataType data; AlarmItem item;
// 拿到现在的时间 // 拿到现在的时间
auto now = DateTime::Now(); auto now = DateTime::Now();
now.Ms = 0; now.Ms = 0;
for (int i = 0; i < NextAlarmIds.Count(); i++) for (int i = 0; i < NextAlarmIds.Count(); i++)
{ {
byte NextAlarmId = NextAlarmIds[i]; byte NextAlarmId = NextAlarmIds[i];
GetCfg(NextAlarmId, data); GetCfg(NextAlarmId, item);
// 拿到定时项的时间 // 拿到定时项的时间
DateTime dt(now.Year, now.Month, now.Day); DateTime dt(now.Year, now.Month, now.Day);
dt.Hour = data.Hour; dt.Hour = item.Hour;
dt.Minute = data.Minutes; dt.Minute = item.Minutes;
dt.Second = dt.Second; dt.Second = dt.Second;
dt.Ms = 0; dt.Ms = 0;
// 对比现在时间和定时项的时间 符合则执行任务 // 对比现在时间和定时项的时间 符合则执行任务
@ -256,17 +221,17 @@ void Alarm::AlarmTask()
{ {
// 第一个字节 有效数据长度,第二个字节动作类型,后面是数据 // 第一个字节 有效数据长度,第二个字节动作类型,后面是数据
// 取总体数据长度 // 取总体数据长度
byte len = data.Data[0]; byte len = item.Data[0];
if (len <= 10) if (len <= 10)
{ {
// 取动作类型 // 取动作类型
auto type = (int)data.Data[1]; auto type = (int)item.Data[1];
AlarmActuator acttor; AlarmExecutor acttor;
if (dic.TryGetValue(type, acttor)) if (dic.TryGetValue(type, acttor))
{ {
// 取动作数据 // 取动作数据
Buffer bs(&data.Data[2], len - 1); Buffer bs(&item.Data[2], len - 1);
// 执行动作 DoSomething(data); // 执行动作 DoSomething(item);
acttor(NextAlarmId, bs); acttor(NextAlarmId, bs);
} }
} }
@ -290,7 +255,7 @@ void Alarm::Start()
Sys.SetTask(AlarmTaskId, true, 0); Sys.SetTask(AlarmTaskId, true, 0);
} }
void Alarm::Register(byte type, AlarmActuator act) void Alarm::Register(byte type, AlarmExecutor act)
{ {
dic.Add((int)type, act); dic.Add((int)type, act);
} }

View File

@ -9,27 +9,27 @@
#include "Message\DataStore.h" #include "Message\DataStore.h"
/* /*
TokenClient Policy/AlarmSet TokenClient Policy/Set
TokenClient Policy/AlarmGet TokenClient Policy/Get
Action = Policy/AlarmSet alarm = AlarmDataType Action = Policy/Set alarm = AlarmItem
Action = Policy/AlarmGet Action = Policy/Get
AlarmSet Set
1. AlarmDataType.number = 0 Enable = false的编号进行存储 1. AlarmItem.number = 0 Enable = false的编号进行存储
number进行储存和执行 number进行储存和执行
2. AlarmDataType.Data 2. AlarmItem.Data
3. AlarmDataType.Data = (1byte)len + (1byte)type + (len-1 byte)data[] 3. AlarmItem.Data = (1byte)len + (1byte)type + (len-1 byte)data[]
type type跟函数 bsp里进行注册 type type跟函数 bsp里进行注册
AlarmGet Get
20 20
*/ */
// 执行定时器的函数类型 // 执行定时器的函数类型
typedef void(*AlarmActuator)(byte type, Buffer& bs); typedef void(*AlarmExecutor)(byte type, Buffer& bs);
typedef struct typedef struct
{ {
@ -50,16 +50,17 @@ public:
#pragma pack(push) // 保存对齐状态 #pragma pack(push) // 保存对齐状态
// 强制结构体紧凑分配空间 // 强制结构体紧凑分配空间
#pragma pack(1) #pragma pack(1)
//
typedef struct typedef struct
{ {
byte Number; // 闹钟编号 byte Index; // 闹钟编号
byte Enable; // 是否有效 byte Enable; // 是否有效
AlarmType Type; // week相关 AlarmType Type; // week相关
byte Hour; // 时 byte Hour; // 时
byte Minutes; // 分 byte Minutes; // 分
byte Seconds; // 秒 byte Seconds; // 秒
byte Data[11]; // 第一个字节 有效数据长度,第二个字节动作类型,后面是数据 byte Data[10]; // 第一个字节 有效数据长度,第二个字节动作类型,后面是数据
}AlarmDataType; }AlarmItem;
#pragma pack(pop) // 恢复对齐状态 #pragma pack(pop) // 恢复对齐状态
class Alarm class Alarm
@ -67,30 +68,31 @@ class Alarm
public: public:
Alarm(); Alarm();
/* 注册给 TokenClient 名称 Policy/AlarmSet */ /* 注册给 TokenClient 名称 Policy/Set */
bool AlarmSet(const Pair& args, Stream& result); bool Set(const Pair& args, Stream& result);
/* 注册给 TokenClient 名称 Policy/AlarmGet */ /* 注册给 TokenClient 名称 Policy/Get */
bool AlarmGet(const Pair& args, Stream& result); bool Get(const Pair& args, Stream& result) const;
// Config
byte SetCfg(byte id, AlarmDataType& data);
bool GetCfg(byte id, AlarmDataType& data);
void Start(); void Start();
// 注册执行动作的函数 // 注册执行动作的函数
void Register(byte type, AlarmActuator act); void Register(byte type, AlarmExecutor act);
private: private:
Dictionary<int, AlarmActuator> dic;// AlarmDataType.Data[1] 表示动作类型,由此字典进行匹配动作执行器 Dictionary<int, AlarmExecutor> dic;// AlarmItem.Data[1] 表示动作类型,由此字典进行匹配动作执行器
uint AlarmTaskId; // 闹钟TaskId uint AlarmTaskId; // 闹钟TaskId
List<int>NextAlarmIds; // 下次运行的编号,允许多组定时器定时时间相同 List<int> NextAlarmIds; // 下次运行的编号,允许多组定时器定时时间相同
int NextAlarmMs; // 下次闹钟时间 int NextAlarmMs; // 下次闹钟时间
// Task // Task
void AlarmTask(); void AlarmTask();
// 找到最近的闹钟时间的id以及时间 // 找到最近的闹钟的id以及时间
byte FindNext(int& nextTime); byte FindNext(int& nextTime);
// 计算下次闹钟时间 // 计算下次闹钟时间
int CalcNextTime(AlarmDataType& data); int CalcNextTime(AlarmItem& item);
// Config
byte SetCfg(const AlarmItem& item);
bool GetCfg(byte id, AlarmItem& item);
}; };

View File

@ -448,14 +448,14 @@ void AlarmWrite(byte type, Buffer& bs)
debug_printf("AlarmWrite type %d data ", type); debug_printf("AlarmWrite type %d data ", type);
bs.Show(true); bs.Show(true);
//auto tc = AP0801::Current->Client; // auto tc = AP0801::Current->Client;
auto tc = Client; // auto tc = Client;
Stream ms(bs); // Stream ms(bs);
auto start = ms.ReadByte(); // auto start = ms.ReadByte();
Buffer data(bs.GetBuffer() + 1, bs.Length() - 1); // Buffer data(bs.GetBuffer() + 1, bs.Length() - 1);
tc->Store.Write(start, data); Client->Store.Write(bs[0], bs.Sub(1));
} }
void AlarmReport(byte type, Buffer&bs) void AlarmReport(byte type, Buffer&bs)
@ -463,13 +463,13 @@ void AlarmReport(byte type, Buffer&bs)
debug_printf("AlarmReport type %d data ", type); debug_printf("AlarmReport type %d data ", type);
bs.Show(true); bs.Show(true);
Stream ms(bs); // Stream ms(bs);
auto start = ms.ReadByte(); // auto start = ms.ReadByte();
auto size = ms.ReadByte(); // auto size = ms.ReadByte();
//auto tc = AP0801::Current->Client; // //auto tc = AP0801::Current->Client;
auto tc = Client; // auto tc = Client;
tc->ReportAsync(start, size); Client->ReportAsync(bs[0], bs[1]);
} }
void AlarmDelayOpen(void *param) void AlarmDelayOpen(void *param)
@ -481,8 +481,8 @@ void AlarmDelayOpen(void *param)
alarm->Start(); alarm->Start();
Sys.RemoveTask(Task::Current().ID); Sys.RemoveTask(Task::Current().ID);
} }
else // else
Sys.SetTask(Task::Current().ID, true, 2000); // Sys.SetTask(Task::Current().ID, true, 2000);
} }
void AP0801::InitAlarm() void AP0801::InitAlarm()
@ -490,8 +490,8 @@ void AP0801::InitAlarm()
if (!Client)return; if (!Client)return;
if (!AlarmObj)AlarmObj = new Alarm(); if (!AlarmObj)AlarmObj = new Alarm();
Client->Register("Policy/AlarmSet", &Alarm::AlarmSet, AlarmObj); Client->Register("Policy/Set", &Alarm::Set, AlarmObj);
Client->Register("Policy/AlarmGet", &Alarm::AlarmGet, AlarmObj); Client->Register("Policy/Get", &Alarm::Get, AlarmObj);
AlarmObj->Register(5, AlarmWrite); AlarmObj->Register(5, AlarmWrite);
AlarmObj->Register(6, AlarmReport); AlarmObj->Register(6, AlarmReport);