source: azure_iot_hub/trunk/ntshell/echonet/echonet_agent.c@ 388

Last change on this file since 388 was 388, checked in by coas-nagasima, 5 years ago

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 27.9 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2015 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者
7は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再é…
10å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
11 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
12 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13 * スコード中に含まれていること.
14 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
15 * 用できる形で再é…
16å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
17å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
18 * 者
19マニュアルなど)に,上記の著作権表示,この利用条件および下記
20 * の無保証規定を掲載すること.
21 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22 * 用できない形で再é…
23å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
24 * と.
25 * (a) 再é…
26å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
27マニュアルなど)に,上記の著
28 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
29 * (b) 再é…
30å¸ƒã®å½¢æ…
31‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
32 * 報告すること.
33 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
34 * 害からも,上記著作権者
35およびTOPPERSプロジェクトをå…
36è²¬ã™ã‚‹ã“と.
37 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
38 * 由に基づく請求からも,上記著作権者
39およびTOPPERSプロジェクトを
40 * å…
41è²¬ã™ã‚‹ã“と.
42 *
43 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
44お
45 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
46 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
47 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
48 * の責任を負わない.
49 *
50 * @(#) $Id: echonet_agent.c 388 2019-05-22 11:25:18Z coas-nagasima $
51 */
52
53/*
54 * ECHONET Lite 動的生成ノード
55 */
56
57#ifdef ECHONET_CONTROLLER_EXTENTION
58
59#include <kernel.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <stdarg.h>
63#include <string.h>
64#include <t_syslog.h>
65#include "echonet.h"
66#include "echonet_fbs.h"
67#include "echonet_agent.h"
68#include "echonet_task.h"
69#include "echonet_lcl_task.h"
70
71typedef struct ecn_agent_buffer
72{
73 union{
74 struct ecn_agent_buffer *free;
75 ecn_agent_queue_t queue;
76 };
77 union{
78 ecn_obj_t obj;
79 ecn_node_t node;
80 ecn_device_t device;
81 };
82} ecn_agent_buffer_t;
83
84typedef struct ecn_agent
85{
86 EPRPINIB eprpinib;
87 ecn_agent_queue_t nodes;
88 ecn_node_t *current_node;
89 bool_t msg_proced;
90 int blkpos;
91 ecn_agent_buffer_t *free;
92 ecn_agent_buffer_t blockes[TNUM_AEOBJID];
93 int requestid;
94} ecn_agent_t;
95
96static ER ecn_agent_proc_get_device_list(ecn_agent_t *agent, ECN_FBS_ID req);
97static ER ecn_agent_proc_get_device_info(ecn_agent_t *agent, ECN_FBS_ID req);
98static void ecn_node_send_set_prop_map(ecn_node_t *node);
99static void ecn_node_send_get_prop_map(ecn_node_t *node);
100static void ecn_node_send_anno_prop_map(ecn_node_t *node);
101static void ecn_node_timeout_on_start(ecn_node_t *node);
102static void ecn_node_next_proc_on_set_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj);
103static void ecn_node_timeout_on_set_prpmap_wait(ecn_node_t *node);
104static void ecn_node_next_proc_on_get_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj);
105static void ecn_node_timeout_on_get_prpmap_wait(ecn_node_t *node);
106static void ecn_node_next_proc_on_anno_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj);
107static void ecn_node_timeout_on_anno_prpmap_wait(ecn_node_t *node);
108
109int ecn_agent_eprpset(const EPRPINIB *item, const void *src, int size, bool_t *anno);
110int ecn_agent_eprpget(const EPRPINIB *item, void *dst, int size);
111
112static ecn_agent_queue_t *cast_queue(ecn_obj_t *obj)
113{
114 return (ecn_agent_queue_t *)((intptr_t)obj - offsetof(ecn_agent_buffer_t, obj));
115}
116
117static ecn_obj_t *cast_obj(ecn_agent_queue_t *queue)
118{
119 return (ecn_obj_t *)((intptr_t)queue + offsetof(ecn_agent_buffer_t, obj));
120}
121
122static ecn_node_t *cast_node(const EOBJCB *eobj)
123{
124 return (ecn_node_t *)((intptr_t)eobj - offsetof(ecn_node_t, eobj));
125}
126
127static ecn_obj_t *cast_obj2(const EOBJINIB *inib)
128{
129 return (ecn_obj_t *)((intptr_t)inib - offsetof(ecn_obj_t, inib));
130}
131
132static ecn_agent_t *cast_agent(const EPRPINIB *inib)
133{
134 return (ecn_agent_t *)((intptr_t)inib - offsetof(ecn_agent_t, eprpinib));
135}
136
137ecn_agent_t g_ecn_agent = {
138 /*eprpinib*/{
139 0x00,
140 EPC_RULE_SET | EPC_RULE_GET,
141 255,
142 (intptr_t)&g_ecn_agent,
143 ecn_agent_eprpset,
144 ecn_agent_eprpget
145 },
146};
147
148ER get_buf(ecn_agent_t *agent, ecn_agent_buffer_t **buf)
149{
150 ER ret = E_OK;
151
152 loc_cpu();
153
154 if (agent->blkpos < TNUM_AEOBJID) {
155 *buf = &agent->blockes[agent->blkpos++];
156 }
157 else if (agent->free == NULL) {
158 ret = E_TMOUT;
159 }
160 else{
161 *buf = agent->free;
162 agent->free = agent->free->free;
163 }
164
165 unl_cpu();
166
167 return ret;
168}
169
170ER rel_buf(ecn_agent_t *agent, ecn_agent_buffer_t *buf)
171{
172 if ((buf < &agent->blockes[0]) || (buf >= &agent->blockes[TNUM_AEOBJID]))
173 return E_PAR;
174
175 if ((((intptr_t)buf - (intptr_t)&agent->blockes[0]) % sizeof(ecn_agent_buffer_t)) != 0)
176 return E_PAR;
177
178 loc_cpu();
179
180 if (agent->free == NULL) {
181 agent->free = buf;
182 agent->free->free = NULL;
183 }
184 else {
185 ecn_agent_buffer_t *next = agent->free;
186 agent->free = buf;
187 agent->free->free = next;
188 }
189
190 unl_cpu();
191
192 return E_OK;
193}
194
195/*
196 * キューの初期化
197 *
198 * p_queueにはキューヘッダを指定する.
199 */
200Inline void
201ecn_agent_queue_init(ecn_agent_queue_t *p_queue)
202{
203#ifdef _DEBUG
204 p_queue->p_parent = p_queue;
205#endif
206 p_queue->p_prev = p_queue;
207 p_queue->p_next = p_queue;
208}
209
210/*
211 * キューの前エントリへの挿å…
212¥
213 *
214 * p_queueの前にp_entryを挿å…
215¥ã™ã‚‹ï¼Žp_queueにキューヘッダを指定した場
216 * 合には,キューの末尾にp_entryを挿å…
217¥ã™ã‚‹ã“とになる.
218 */
219Inline void
220ecn_agent_queue_add(ecn_agent_queue_t *p_queue, ecn_agent_queue_t *p_entry)
221{
222#ifdef _DEBUG
223 assert((p_queue->p_parent == p_queue) && (p_entry->p_parent == NULL));
224 p_entry->p_parent = p_queue;
225#endif
226 p_entry->p_prev = p_queue->p_prev;
227 p_entry->p_next = p_queue;
228 p_queue->p_prev->p_next = p_entry;
229 p_queue->p_prev = p_entry;
230}
231
232/*
233 * エントリの削除
234 *
235 * p_entryをキューから削除する.
236 */
237Inline void
238ecn_agent_queue_remove(ecn_agent_queue_t *p_queue, ecn_agent_queue_t *p_entry)
239{
240#ifdef _DEBUG
241 assert((p_queue->p_parent == p_queue) && (p_entry->p_parent == p_queue));
242 p_entry->p_parent = NULL;
243#endif
244 p_entry->p_prev->p_next = p_entry->p_next;
245 p_entry->p_next->p_prev = p_entry->p_prev;
246}
247
248ecn_node_t *ecn_agent_find_node(ECN_ENOD_ID enodid)
249{
250 ecn_agent_t *agent = &g_ecn_agent;
251 ecn_agent_queue_t *queue = agent->nodes.p_next;
252#ifdef _DEBUG
253 assert(queue->p_parent == &agent->nodes);
254#endif
255 for (; queue != &agent->nodes; queue = queue->p_next) {
256 ecn_node_t *node = (ecn_node_t *)cast_obj(queue);
257 if(node->enodId == enodid)
258 return node;
259 }
260
261 return NULL;
262}
263
264ecn_node_t *ecn_agent_find_node2(const EOBJCB *pk_eobj)
265{
266 ecn_agent_t *agent = &g_ecn_agent;
267 ecn_agent_queue_t *queue;
268
269 if(pk_eobj == NULL)
270 return NULL;
271
272 queue = agent->nodes.p_next;
273#ifdef _DEBUG
274 assert(queue->p_parent == &agent->nodes);
275#endif
276 for (; queue != &agent->nodes; queue = queue->p_next) {
277 ecn_node_t *node = (ecn_node_t *)cast_obj(queue);
278 if(&node->eobj == pk_eobj)
279 return node;
280 }
281
282 return NULL;
283}
284
285ecn_obj_t *ecn_agent_find_eobj(const EOBJCB *pk_nod, T_ECN_EOJ eoj)
286{
287 ecn_agent_queue_t *devices = &cast_node(pk_nod)->devices;
288 ecn_agent_queue_t *queue = devices->p_next;
289#ifdef _DEBUG
290 assert(queue->p_parent == devices);
291#endif
292 for (; queue != devices; queue = queue->p_next) {
293 ecn_obj_t *obj = cast_obj(queue);
294 if (obj->inib.eojx1 != eoj.eojx1)
295 continue;
296 if (obj->inib.eojx2 != eoj.eojx2)
297 continue;
298 if (obj->inib.eojx3 != eoj.eojx3)
299 continue;
300
301 return obj;
302 }
303
304 return NULL;
305}
306
307ecn_obj_t *ecn_agent_find_obj2(ecn_node_t *pk_nod, const EOBJINIB *pk_obj)
308{
309 ecn_agent_queue_t *devices = &pk_nod->devices;
310 ecn_agent_queue_t *queue = devices->p_next;
311#ifdef _DEBUG
312 assert(queue->p_parent == devices);
313#endif
314 for (; queue != devices; queue = queue->p_next) {
315 ecn_obj_t *obj = cast_obj(queue);
316 if (&obj->inib == pk_obj)
317 return obj;
318 }
319
320 return NULL;
321}
322
323ID ecn_agent_get_eobj(const EOBJINIB *pk_obj)
324{
325 return cast_obj2(pk_obj)->eobjId;
326}
327
328const EOBJINIB *ecn_agent_next_eobj(const EOBJCB *pk_nod, const EOBJINIB *pk_obj)
329{
330 ecn_agent_queue_t *devices = &cast_node(pk_nod)->devices;
331 ecn_obj_t *device = (ecn_obj_t *)pk_obj->exinf;
332 ecn_agent_queue_t *queue = cast_queue(device);
333#ifdef _DEBUG
334 assert(queue->p_parent == devices);
335#endif
336 if (queue == devices)
337 return NULL;
338
339 return &cast_obj(queue->p_next)->inib;
340}
341
342bool_t ecn_agent_get_eoj_enodid(ID eobjid, T_ECN_EOJ *eoj, ECN_ENOD_ID *enodid)
343{
344 ecn_agent_t *agent = &g_ecn_agent;
345 ecn_agent_buffer_t *buf;
346 int i = eobjid;
347
348 /* オブジェクトIDから実体を取得 */
349 i -= (tmax_eobjid + 1);
350 if ((i < 0)
351 || (i >= (sizeof(agent->blockes) / sizeof(agent->blockes[0])))){
352 return false;
353 }
354
355 buf = &agent->blockes[i];
356 if(buf->obj.eobjId != eobjid)
357 return false;
358
359 /* オブジェクトのEOJをコピー */
360 memcpy(eoj, &buf->obj.inib.eojx1, sizeof(*eoj));
361
362 /* 所属するノードのオブジェクトIDを取得 */
363 if(buf->obj.inib.enodid == 0)
364 i = buf->obj.eobjId;
365 else
366 i = buf->obj.inib.enodid;
367
368 i -= (tmax_eobjid + 1);
369 if ((i < 0)
370 || (i >= (sizeof(agent->blockes) / sizeof(agent->blockes[0])))){
371 return false;
372 }
373
374 /* ノードIDを取得 */
375 buf = &agent->blockes[i];
376 *enodid = buf->node.enodId;
377
378 return true;
379}
380
381void ecn_agent_set_epc_to_prop_map(uint8_t epc, uint8_t *propMap)
382{
383 int i, j;
384 assert((epc & 0x80) != 0);
385 i = epc & 0xF;
386 j = (epc >> 4) - 8;
387 propMap[i] |= (1 << j);
388}
389
390bool_t ecn_agent_contains_epc_in_prop_map(uint8_t epc, uint8_t *propMap)
391{
392 int i, j;
393 assert((epc & 0x80) != 0);
394 i = epc & 0xF;
395 j = (epc >> 4) - 8;
396 return (propMap[i] & (1 << j)) != 0;
397}
398
399void ecn_agent_init(void)
400{
401 ecn_agent_queue_init(&g_ecn_agent.nodes);
402}
403
404ecn_node_t *ecn_agent_create_node(ecn_agent_t *agent, T_EDATA *esv)
405{
406 ecn_agent_buffer_t *result = NULL;
407 ecn_node_t *node = NULL;
408 uint8_t epc;
409 uint8_t pdc;
410 uint8_t edt[256];
411 T_ENUM_EPC enm;
412 ER ret;
413 T_ECN_EOJ *eoj, *end;
414
415 // プロパティ通知か取得応答で、
416 switch (esv->hdr.edata.esv) {
417 case ESV_GET_RES:
418 case ESV_GET_SNA:
419 case ESV_INF:
420 break;
421 default:
422 return NULL;
423 }
424
425 // ノードプロファイル宛の場合
426 eoj = &esv->hdr.edata.seoj;
427 if ((eoj->eojx1 != EOJ_X1_PROFILE) || (eoj->eojx2 != EOJ_X2_NODE_PROFILE)
428 || (eoj->eojx3 != 0x01))
429 return NULL;
430
431 ret = ecn_itr_ini(&enm, esv);
432 if(ret != E_OK){
433 syslog(LOG_WARNING, "ecn_itr_ini");
434 }
435
436 while (ecn_itr_nxt(&enm, &epc, &pdc, &edt) == E_OK) {
437 switch (epc) {
438 // インスタンスリスト通知の場合
439 case 0xD5:
440 // 自ノードインスタンスリストS通知の場合
441 case 0xD6:
442 // サイズが合わない場合
443 if (pdc != (1 + edt[0] * sizeof(T_ECN_EOJ)))
444 return NULL;
445
446 ret = get_buf(agent, &result);
447 if(ret != E_OK){
448 syslog(LOG_WARNING, "get_buf");
449 return NULL;
450 }
451
452 memset(result, 0, sizeof(*result));
453 node = &result->node;
454 node->enodId = ((T_ECN_FST_BLK *)esv)->hdr.sender.id;
455 node->base.eobjId = tmax_eobjid + 1 + (((intptr_t)result - (intptr_t)agent->blockes) / sizeof(agent->blockes[0]));
456 node->base.inib.enodid = 0;
457 node->base.inib.eobjatr = EOBJ_SYNC_REMOTE_NODE;
458 node->base.inib.exinf = (intptr_t)node;
459 node->base.inib.eojx1 = eoj->eojx1;
460 node->base.inib.eojx2 = eoj->eojx2;
461 node->base.inib.eojx3 = eoj->eojx3;
462 node->base.inib.eprp = &agent->eprpinib;
463 node->base.inib.eprpcnt = 0;
464 ecn_agent_set_epc_to_prop_map(0xD5, node->base.pmapGet);
465 ecn_agent_set_epc_to_prop_map(0xD6, node->base.pmapGet);
466 ecn_agent_set_epc_to_prop_map(0x9D, node->base.pmapGet);
467 ecn_agent_set_epc_to_prop_map(0x9E, node->base.pmapGet);
468 ecn_agent_set_epc_to_prop_map(0x9F, node->base.pmapGet);
469 ecn_agent_queue_init(&node->devices);
470 node->eobj.profile = &node->base.inib;
471 node->eobj.eobjs = NULL;
472 node->eobj.eobjcnt = pdc / 3;
473 node->state = ecn_node_state_idle;
474 node->timer = TMO_FEVR;
475
476 end = (T_ECN_EOJ *)&edt[pdc];
477 for (eoj = (T_ECN_EOJ *)&edt[1]; eoj < end; eoj++) {
478 ecn_device_t *device;
479 ecn_agent_buffer_t *obj;
480
481 ret = get_buf(agent, &obj);
482 if(ret != E_OK){
483 syslog(LOG_WARNING, "get_buf");
484 return NULL;
485 }
486
487 memset(obj, 0, sizeof(*obj));
488 device = &obj->device;
489 device->node = node;
490 device->base.eobjId = tmax_eobjid + 1 + (((intptr_t)obj - (intptr_t)agent->blockes) / sizeof(agent->blockes[0]));
491 device->base.inib.eobjatr = EOBJ_DEVICE;
492 device->base.inib.enodid = node->base.eobjId;
493 device->base.inib.exinf = (intptr_t)device;
494 device->base.inib.eojx1 = eoj->eojx1;
495 device->base.inib.eojx2 = eoj->eojx2;
496 device->base.inib.eojx3 = eoj->eojx3;
497 device->base.inib.eprp = &agent->eprpinib;
498 device->base.inib.eprpcnt = 0;
499 ecn_agent_set_epc_to_prop_map(0x9D, device->base.pmapGet);
500 ecn_agent_set_epc_to_prop_map(0x9E, device->base.pmapGet);
501 ecn_agent_set_epc_to_prop_map(0x9F, device->base.pmapGet);
502
503 ecn_agent_queue_add(&node->devices, &obj->queue);
504 }
505 break;
506 default:
507 continue;
508 }
509 break;
510 }
511
512 if (result == NULL)
513 return NULL;
514
515 ecn_agent_queue_add(&agent->nodes, &result->queue);
516
517 return node;
518}
519
520static ER ecn_agent_proc_get_device_list(ecn_agent_t *agent, ECN_FBS_ID req)
521{
522 ER ret;
523 ECN_FBS_ID res;
524 ecn_inm_get_device_list_req_t msg;
525 ECN_FBS_SSIZE_T len;
526 ecn_agent_buffer_t *pos, *end = &agent->blockes[TNUM_AEOBJID];
527 ecn_inm_get_device_item_t item;
528
529 ret = _ecn_fbs_get_data(req, &msg, sizeof(msg), &len);
530 if (ret != E_OK) {
531 return ret;
532 }
533
534 ret = _ecn_tsk_cre_res_fbs(req, ECN_INM_GET_DEVICE_LIST_RES, &res);
535 if (ret != E_OK) {
536 return ret;
537 }
538
539 ret = _ecn_fbs_add_data_ex(res, &msg.requestid, sizeof(((ecn_inm_get_device_list_res_t *)0)->requestid));
540 if (ret != E_OK) {
541 _ecn_fbs_del(res);
542 return ret;
543 }
544
545 for (pos = &agent->blockes[0]; pos < end; pos++){
546 if(pos->obj.eobjId == 0)
547 continue;
548
549 item.eobjid = pos->obj.eobjId;
550 item.enodid = pos->obj.inib.enodid;
551 item.eojx1 = pos->obj.inib.eojx1;
552 item.eojx2 = pos->obj.inib.eojx2;
553 item.eojx3 = pos->obj.inib.eojx3;
554
555 if(pos->device.node != NULL)
556 item.addrid = pos->device.node->enodId;
557 else
558 item.addrid = pos->node.enodId;
559
560 ret = _ecn_fbs_add_data_ex(res, &item, sizeof(item));
561 if (ret != E_OK) {
562 _ecn_fbs_del(res);
563 return ret;
564 }
565 }
566
567 ret = psnd_dtq(res.ptr->hdr.target.dtqid, (intptr_t)res.ptr);
568 if (ret != E_OK) {
569 _ecn_fbs_del(res);
570 return ret;
571 }
572
573 return E_OK;
574}
575
576static ER ecn_agent_proc_get_device_info(ecn_agent_t *agent, ECN_FBS_ID req)
577{
578 ER ret;
579 ECN_FBS_ID res;
580 ecn_inm_get_device_info_req_t msg;
581 ecn_inm_get_device_info_res_t rmsg;
582 ECN_FBS_SSIZE_T len;
583 int eobjId;
584 ecn_agent_buffer_t *pos;
585
586 ret = _ecn_fbs_get_data(req, &msg, sizeof(msg), &len);
587 if (ret != E_OK) {
588 return ret;
589 }
590
591 eobjId = msg.eobjid - tmax_eobjid - 1;
592 pos = &agent->blockes[eobjId];
593
594 ret = _ecn_tsk_cre_res_fbs(req, ECN_INM_GET_DEVICE_INFO_RES, &res);
595 if (ret != E_OK) {
596 return ret;
597 }
598
599 rmsg.requestid = msg.requestid;
600 rmsg.eobjid = pos->obj.eobjId;
601 memcpy(rmsg.pmapSet, pos->obj.pmapSet, sizeof(rmsg.pmapSet));
602 memcpy(rmsg.pmapGet, pos->obj.pmapGet, sizeof(rmsg.pmapGet));
603 memcpy(rmsg.pmapAnno, pos->obj.pmapAnno, sizeof(rmsg.pmapAnno));
604 rmsg.eprpcnt = pos->obj.eprpcnt;
605
606 ret = _ecn_fbs_add_data_ex(res, &rmsg, sizeof(rmsg));
607 if (ret != E_OK) {
608 _ecn_fbs_del(res);
609 return ret;
610 }
611
612 ret = psnd_dtq(res.ptr->hdr.target.dtqid, (intptr_t)res.ptr);
613 if (ret != E_OK) {
614 _ecn_fbs_del(res);
615 return ret;
616 }
617
618 return E_OK;
619}
620
621int ecn_agent_get_timer()
622{
623 int timer = TMO_FEVR, temp;
624 ecn_agent_t *agent = &g_ecn_agent;
625 ecn_node_t *node;
626 ecn_agent_queue_t *queue;
627
628 queue = &agent->nodes;
629 for (;;) {
630 queue = queue->p_next;
631#ifdef _DEBUG
632 assert(queue->p_parent == &agent->nodes);
633#endif
634 if(&agent->nodes == queue)
635 break;
636
637 node = (ecn_node_t *)cast_obj(queue);
638 temp = node->timer;
639 if (temp != TMO_FEVR) {
640 if ((timer == TMO_FEVR) || (temp < timer)) {
641 timer = temp;
642 }
643 }
644 }
645
646 return timer;
647}
648
649void ecn_agent_progress(int interval)
650{
651 ecn_agent_t *agent = &g_ecn_agent;
652 ecn_node_t *node;
653 ecn_agent_queue_t *queue;
654
655 queue = &agent->nodes;
656 for (;;) {
657 queue = queue->p_next;
658#ifdef _DEBUG
659 assert(queue->p_parent == &agent->nodes);
660#endif
661 if(&agent->nodes == queue)
662 break;
663
664 node = (ecn_node_t *)cast_obj(queue);
665 if (node->timer == TMO_FEVR)
666 continue;
667
668 node->timer -= interval;
669 if (node->timer <= 0) {
670 node->timer = 0;
671 }
672 }
673}
674
675void ecn_agent_timeout()
676{
677 ecn_agent_t *agent = &g_ecn_agent;
678 ecn_node_t *node;
679 ecn_agent_queue_t *queue;
680
681 queue = &agent->nodes;
682 for (;;) {
683 queue = queue->p_next;
684#ifdef _DEBUG
685 assert(queue->p_parent == &agent->nodes);
686#endif
687 if(&agent->nodes == queue)
688 break;
689
690 node = (ecn_node_t *)cast_obj(queue);
691 if (node->timer != 0)
692 continue;
693
694 switch (node->state) {
695 case ecn_node_state_start:
696 ecn_node_timeout_on_start(node);
697 break;
698 case ecn_node_state_set_prpmap_wait:
699 ecn_node_timeout_on_set_prpmap_wait(node);
700 break;
701 case ecn_node_state_get_prpmap_wait:
702 ecn_node_timeout_on_get_prpmap_wait(node);
703 break;
704 case ecn_node_state_anno_prpmap_wait:
705 ecn_node_timeout_on_anno_prpmap_wait(node);
706 break;
707 default:
708 assert(0);
709 }
710 }
711}
712
713bool_t ecn_agent_proc_int_msg(ECN_FBS_ID fbs, uint8_t cmd)
714{
715 ecn_agent_t *agent = &g_ecn_agent;
716
717 switch(cmd)
718 {
719 case ECN_INM_GET_DEVICE_LIST_REQ:
720 ecn_agent_proc_get_device_list(agent, fbs);
721 break;
722 case ECN_INM_GET_DEVICE_INFO_REQ:
723 ecn_agent_proc_get_device_info(agent, fbs);
724 break;
725 default:
726 return false;
727 }
728
729 return true;
730}
731
732void ecn_agent_proc_ecn_msg(const EOBJCB **ppk_snod, const EOBJINIB **ppk_sobj, T_EDATA *esv)
733{
734 ecn_agent_t *agent = &g_ecn_agent;
735 ecn_node_t *snod;
736 ecn_obj_t *sobj;
737
738 /* 静的に定義された送信å…
739ƒã®å ´åˆ */
740 if ((*ppk_snod != NULL) && (*ppk_snod)->eobjs != NULL) {
741 /* 処理しない */
742 return;
743 }
744
745 snod = ecn_agent_find_node2(*ppk_snod);
746
747 /* 送信å…
748ƒã‚’知らなかったら */
749 if (snod == NULL) {
750 /* 送信å…
751ƒã®ãƒŽãƒ¼ãƒ‰æƒ…
752報を新規に作成 */
753 snod = ecn_agent_create_node(agent, esv);
754 if (snod == NULL)
755 return;
756 }
757
758 sobj = ecn_agent_find_obj2(snod, *ppk_sobj);
759
760 /* ノードプロファイルの場合 */
761 if ((esv->hdr.edata.seoj.eojx1 == EOJ_X1_PROFILE)
762 && (esv->hdr.edata.seoj.eojx2 == EOJ_X2_NODE_PROFILE)) {
763 sobj = &snod->base;
764 }
765 /* 機器オブジェクトの場合 */
766 else {
767 sobj = ecn_agent_find_eobj(&snod->eobj, esv->hdr.edata.seoj);
768 }
769
770 *ppk_snod = &snod->eobj;
771 *ppk_sobj = &sobj->inib;
772
773 agent->current_node = snod;
774 agent->msg_proced = false;
775}
776
777void ecn_agent_proc_ecn_msg_end()
778{
779 ecn_agent_t *agent = &g_ecn_agent;
780 ecn_node_t *node = agent->current_node;
781 ecn_obj_t *sobj;
782
783 if(node == NULL)
784 return;
785
786 sobj = node->current;
787 if(sobj == NULL)
788 return;
789
790 if (agent->msg_proced) {
791 switch (node->state) {
792 case ecn_node_state_set_prpmap_wait:
793 ecn_node_next_proc_on_set_prpmap_wait(node, sobj);
794 break;
795 case ecn_node_state_get_prpmap_wait:
796 ecn_node_next_proc_on_get_prpmap_wait(node, sobj);
797 break;
798 case ecn_node_state_anno_prpmap_wait:
799 ecn_node_next_proc_on_anno_prpmap_wait(node, sobj);
800 break;
801 }
802 }
803}
804
805static void ecn_node_send_set_prop_map(ecn_node_t *node)
806{
807 T_EDATA *esv;
808 ecn_obj_t *obj = node->current;
809
810 // プロパティ値読み出し要求
811 ecn_esv_get(&esv, obj->eobjId, 0x9E);
812 ecn_snd_esv(esv);
813
814 node->state = ecn_node_state_set_prpmap_wait;
815 node->timer = 5000 * 1000;
816}
817
818static void ecn_node_send_get_prop_map(ecn_node_t *node)
819{
820 T_EDATA *esv;
821 ecn_obj_t *obj = node->current;
822
823 // プロパティ値読み出し要求
824 ecn_esv_get(&esv, obj->eobjId, 0x9F);
825 ecn_snd_esv(esv);
826
827 node->state = ecn_node_state_get_prpmap_wait;
828 node->timer = 5000 * 1000;
829}
830
831static void ecn_node_send_anno_prop_map(ecn_node_t *node)
832{
833 T_EDATA *esv;
834 ecn_obj_t *obj = node->current;
835
836 // プロパティ値読み出し要求
837 ecn_esv_get(&esv, obj->eobjId, 0x9D);
838 ecn_snd_esv(esv);
839
840 node->state = ecn_node_state_anno_prpmap_wait;
841 node->timer = 5000 * 1000;
842}
843
844static void ecn_node_next_obj(ecn_node_t *node)
845{
846 ecn_obj_t *obj = node->current;
847 ecn_agent_queue_t *queue;
848 ecn_device_t *device;
849
850 /* objが指定されていない場合 */
851 if(obj == NULL){
852 /* このノードを返す */
853 node->current = &node->base;
854 return;
855 }
856 /* ノードの場合 */
857 else if((obj->inib.eojx1 == EOJ_X1_PROFILE) && (obj->inib.eojx2 == EOJ_X2_NODE_PROFILE)){
858 node = (ecn_node_t *)obj;
859
860 /* é…
861ä¸‹ã®æ©Ÿå™¨ã‚’返す */
862 queue = node->devices.p_next;
863 device = (ecn_device_t *)cast_obj(queue);
864 }
865 /* 機器の場合 */
866 else{
867 /* 次の機器を返す */
868 node = ((ecn_device_t *)obj)->node;
869 queue = cast_queue(obj)->p_next;
870 device = (ecn_device_t *)cast_obj(queue);
871 }
872
873 /* その機器が末尾だった場合 */
874 if(&node->devices == queue){
875 node->current = NULL;
876 }
877 else {
878 node->current = &device->base;
879 }
880}
881
882static void ecn_node_timeout_on_start(ecn_node_t *node)
883{
884 for (;;) {
885 ecn_obj_t *obj = node->current;
886 if (obj == NULL) {
887 node->state = ecn_node_state_idle;
888 node->timer = TMO_FEVR;
889 return;
890 }
891
892 if((obj->pmapFlag & PMAP_FLAG_SET) == 0){
893 ecn_node_send_set_prop_map(node);
894 break;
895 }
896 else if((obj->pmapFlag & PMAP_FLAG_GET) == 0){
897 ecn_node_send_get_prop_map(node);
898 break;
899 }
900 else if((obj->pmapFlag & PMAP_FLAG_ANNO) == 0){
901 ecn_node_send_anno_prop_map(node);
902 break;
903 }
904 else{
905 ecn_node_next_obj(node);
906 }
907 }
908}
909
910static void ecn_node_next_proc_on_set_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj)
911{
912 if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
913 ecn_node_send_get_prop_map(node);
914 }
915 else if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
916 ecn_node_send_anno_prop_map(node);
917 }
918 else if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
919 ecn_node_send_set_prop_map(node);
920 }
921 else{
922 ecn_node_next_obj(node);
923 ecn_node_timeout_on_start(node);
924 }
925}
926
927static void ecn_node_timeout_on_set_prpmap_wait(ecn_node_t *node)
928{
929 ecn_obj_t *obj = node->current;
930 if(obj == NULL){
931 node->state = ecn_node_state_idle;
932 node->timer = TMO_FEVR;
933 return;
934 }
935
936 ecn_node_next_proc_on_set_prpmap_wait(node, obj);
937}
938
939static void ecn_node_next_proc_on_get_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj)
940{
941 if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
942 ecn_node_send_anno_prop_map(node);
943 }
944 else if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
945 ecn_node_send_set_prop_map(node);
946 }
947 else if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
948 ecn_node_send_get_prop_map(node);
949 }
950 else{
951 ecn_node_next_obj(node);
952 ecn_node_timeout_on_start(node);
953 }
954}
955
956static void ecn_node_timeout_on_get_prpmap_wait(ecn_node_t *node)
957{
958 ecn_obj_t *obj = node->current;
959 if(obj == NULL){
960 node->state = ecn_node_state_idle;
961 node->timer = TMO_FEVR;
962 return;
963 }
964
965 ecn_node_next_proc_on_get_prpmap_wait(node, obj);
966}
967
968static void ecn_node_next_proc_on_anno_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj)
969{
970 if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
971 ecn_node_send_set_prop_map(node);
972 }
973 else if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
974 ecn_node_send_get_prop_map(node);
975 }
976 else if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
977 ecn_node_send_anno_prop_map(node);
978 }
979 else{
980 ecn_node_next_obj(node);
981 ecn_node_timeout_on_start(node);
982 }
983}
984
985static void ecn_node_timeout_on_anno_prpmap_wait(ecn_node_t *node)
986{
987 ecn_obj_t *obj = node->current;
988 if(obj == NULL){
989 node->state = ecn_node_state_idle;
990 node->timer = TMO_FEVR;
991 return;
992 }
993
994 ecn_node_next_proc_on_anno_prpmap_wait(node, obj);
995}
996
997const EPRPINIB *ecn_agent_get_property(const EOBJINIB *fp_obj, uint8_t fa_epc, const EPRPINIB *item)
998{
999 ecn_obj_t *obj = cast_obj2(fp_obj);
1000 bool_t has = false;
1001
1002 /* ノードの場合はインスタンスリスト通知と自ノードインスタンスリストS通知を必
1003須で受け取る */
1004 if ((fp_obj->enodid == 0) && ((fa_epc == 0xD5) || (fa_epc == 0xD6)))
1005 has = true;
1006 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapGet))
1007 has = true;
1008 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapSet))
1009 has = true;
1010 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapAnno))
1011 has = true;
1012
1013 if(!has)
1014 return NULL;
1015
1016 ((EPRPINIB *)item)->eprpcd = fa_epc;
1017 ((EPRPINIB *)item)->exinf = (intptr_t)fp_obj;
1018
1019 return item;
1020}
1021
1022int ecn_agent_eprpget(const EPRPINIB *item, void *dst, int size)
1023{
1024 return 0;
1025}
1026
1027int ecn_agent_eprpset(const EPRPINIB *item, const void *src, int size, bool_t *anno)
1028{
1029 ecn_agent_t *agent = cast_agent(item);
1030 ecn_node_t *node = agent->current_node;
1031 const uint8_t *edt = (const uint8_t *)src;
1032 ecn_obj_t *sobj = cast_obj2((const EOBJINIB *)item->exinf);
1033 uint8_t eprpcnt;
1034 int i;
1035
1036 switch (item->eprpcd) {
1037 /* インスタンスリスト通知の場合 */
1038 case 0xD5:
1039 /* 自ノードインスタンスリストS通知の場合 */
1040 case 0xD6:
1041 if ((node != NULL) && (node->state == ecn_node_state_idle)) {
1042 ecn_agent_queue_t *devices = &node->devices;
1043 ecn_agent_queue_t *queue = devices->p_next;
1044#ifdef _DEBUG
1045 assert(queue->p_parent == devices);
1046#endif
1047 for (; queue != devices; queue = queue->p_next) {
1048 ecn_obj_t *obj = cast_obj(queue);
1049 obj->pmapFlag = 0;
1050 }
1051 node->base.pmapFlag = 0;
1052 node->state = ecn_node_state_start;
1053 node->timer = 1000 * 1000;
1054 node->current = sobj;
1055 }
1056 break;
1057 /* 通知プロパティマップの場合 */
1058 case 0x9D:
1059 eprpcnt = edt[0];
1060
1061 if (eprpcnt < 16) {
1062 /* サイズチェック */
1063 if (eprpcnt + 1 != size)
1064 return 0;
1065
1066 for (i = 1; i < size; i++)
1067 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapAnno);
1068 }
1069 else {
1070 /* サイズチェック */
1071 if (size != 17)
1072 return 0;
1073
1074 memcpy(sobj->pmapAnno, &edt[1], 16);
1075 }
1076 sobj->eprpcnt = eprpcnt;
1077 sobj->pmapFlag |= PMAP_FLAG_ANNO;
1078 break;
1079 /* SETプロパティマップの場合 */
1080 case 0x9E:
1081 eprpcnt = edt[0];
1082
1083 if (eprpcnt < 16) {
1084 /* サイズチェック */
1085 if (eprpcnt + 1 != size)
1086 return 0;
1087
1088 for (i = 1; i < size; i++)
1089 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapSet);
1090 }
1091 else {
1092 /* サイズチェック */
1093 if (size != 17)
1094 return 0;
1095
1096 memcpy(sobj->pmapSet, &edt[1], 16);
1097 }
1098 sobj->eprpcnt = eprpcnt;
1099 sobj->pmapFlag |= PMAP_FLAG_SET;
1100 break;
1101 /* GETプロパティマップの場合 */
1102 case 0x9F:
1103 eprpcnt = edt[0];
1104
1105 if (eprpcnt < 16) {
1106 /* サイズチェック */
1107 if (eprpcnt + 1 != size)
1108 return 0;
1109
1110 for (i = 1; i < size; i++)
1111 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapGet);
1112 }
1113 else {
1114 /* サイズチェック */
1115 if (size != 17)
1116 return 0;
1117
1118 memcpy(sobj->pmapGet, &edt[1], 16);
1119 }
1120 sobj->eprpcnt = eprpcnt;
1121 sobj->pmapFlag |= PMAP_FLAG_GET;
1122 break;
1123 default:
1124 return 0;
1125 }
1126
1127 agent->msg_proced = true;
1128
1129 return size;
1130}
1131
1132ER ecn_agent_get_device_list(ID sender, int requestid, ECN_FBS_ID *pk_req)
1133{
1134 ER a_ret;
1135 ECN_FBS_ID req;
1136
1137 a_ret = _ecn_tsk_cre_req_fbs(sender, ECN_INM_GET_DEVICE_LIST_REQ, &req);
1138 if (a_ret != E_OK) {
1139 return a_ret;
1140 }
1141
1142 a_ret = _ecn_fbs_add_data_ex(req, &requestid, sizeof(((ecn_inm_get_device_list_req_t *)0)->requestid));
1143 if (a_ret != E_OK) {
1144 _ecn_fbs_del(req);
1145 return a_ret;
1146 }
1147
1148 *pk_req = req;
1149
1150 return E_OK;
1151}
1152
1153ER ecn_agent_get_device_info(ID sender, int requestid, ID eobjid, ECN_FBS_ID *pk_req)
1154{
1155 ER a_ret;
1156 ECN_FBS_ID req;
1157
1158 a_ret = _ecn_tsk_cre_req_fbs(sender, ECN_INM_GET_DEVICE_INFO_REQ, &req);
1159 if (a_ret != E_OK) {
1160 return a_ret;
1161 }
1162
1163 a_ret = _ecn_fbs_add_data_ex(req, &requestid, sizeof(((ecn_inm_get_device_info_req_t *)0)->requestid));
1164 if (a_ret != E_OK) {
1165 _ecn_fbs_del(req);
1166 return a_ret;
1167 }
1168
1169 a_ret = _ecn_fbs_add_data_ex(req, &eobjid, sizeof(((ecn_inm_get_device_info_req_t *)0)->eobjid));
1170 if (a_ret != E_OK) {
1171 _ecn_fbs_del(req);
1172 return a_ret;
1173 }
1174
1175 *pk_req = req;
1176
1177 return E_OK;
1178}
1179
1180#endif /* ECHONET_CONTROLLER_EXTENTION */
Note: See TracBrowser for help on using the repository browser.