source: asp3_tinet_ecnl_arm/trunk/ntshell/echonet/echonet_agent.c@ 352

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

arm向けASP3版ECNLを追加

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