Statistics
| Branch: | Tag: | Revision:

root / tidsense / event.c @ 172:8c8328364b9d

History | View | Annotate | Download (3.3 kB)

1
#include "config.h"
2
3
#include <stdlib.h>
4
#include <string.h>
5
6
#include "scheduler.h"
7
#include "power.h"
8
#include "node.h"
9
#include "network.h"
10
#include "assoc.h"
11
#include "sysclock.h"
12
#include "event.h"
13
14
sched_task_t *event_task;
15
16
event_record_t event_buffer[MAX_EVENTS];
17
uint8_t event_flags = 0;
18
19
bool events_with_status(event_status_t status) {
20
    for(uint8_t i=0; i<MAX_EVENTS; i++) {
21
        if(event_buffer[i].status == status) {
22
            return true;
23
        }
24
    }
25
    return false;
26
}
27
28
void event_mark_transmitted(event_status_t status) {
29
    for(uint8_t i=0; i<MAX_EVENTS; i++) {
30
        if(event_buffer[i].status == EVENT_TRANSMITTED) {
31
            event_buffer[i].status = status;
32
        }
33
    }
34
}
35
36
void event_confirm(NWK_DataReq_t *req) {
37
    if(req->status == NWK_SUCCESS_STATUS) {
38
        event_mark_transmitted(EVENT_FREE);
39
        event_flags = 0;
40
    } else {
41
        event_mark_transmitted(EVENT_PENDING);
42
        event_flags |= EVENT_FLAG_RETRANSMIT;
43
    }
44
    network_free_request(req);
45
}
46
47
void event_task_fn(void *data) {
48
    // only if we have a master
49
    if(assoc_get_state() != ASSOC_STATE_ASSOCIATED) return;
50
    
51
    if(!events_with_status(EVENT_PENDING)) return;
52
    
53
    // Don't continue if there are currently events in the air
54
    if(events_with_status(EVENT_TRANSMITTED)) return;
55
56
57
    NWK_DataReq_t *req = network_alloc_request(1);
58
    if(!req) return;
59
    
60
    power_radio_on();
61
62
    req->dstAddr = assoc_get_master();
63
    req->dstEndpoint = CONTROL_ENDPOINT;
64
    req->srcEndpoint = CONTROL_ENDPOINT;
65
    req->options = NWK_OPT_ACK_REQUEST;
66
    req->confirm = event_confirm;
67
    req->size = sizeof(event_report_t);
68
69
    event_report_t *report = (event_report_t*)req->data;
70
    report->header.cmd = CMD_EVENT_REPORT;
71
    report->header.flags = 0;
72
    report->header.id = cmd_get_next_id();
73
74
    report->n = 0;
75
    report->flags = event_flags;
76
    sysclock_get_time(&report->timestamp, NULL);
77
78
    for(uint8_t i=0; i<MAX_EVENTS; i++) {
79
        event_record_t *e = &event_buffer[i];
80
        if(e->status == EVENT_PENDING) {
81
            e->status = EVENT_TRANSMITTED;
82
            memcpy(&req->data[req->size], e, sizeof(event_record_t));
83
            req->size += sizeof(event_record_t);
84
            report->n++;
85
        }
86
87
        // keep from overfilling a packet; events not sent here will get
88
        // handled on the next iteration
89
        if(req->size >= 100) break;
90
    }
91
92
    NWK_DataReq(req);
93
}
94
95
event_record_t *event_get_free(void) {
96
    event_record_t *oldest = NULL;
97
    uint32_t oldest_ts = 2147483647UL;
98
    for(uint8_t i=0; i<MAX_EVENTS; i++) {
99
        event_record_t *e = &event_buffer[i];
100
        if(e->status == EVENT_FREE) return e;
101
        if(e->timestamp < oldest_ts) {
102
            oldest = e;
103
            oldest_ts = e->timestamp;
104
        }
105
    }
106
    event_flags |= EVENT_FLAG_OVERFLOW;
107
    oldest->status = EVENT_FREE;
108
    return oldest;
109
}   
110
111
void event_create(event_type_t event, uint32_t data, uint8_t priority) {
112
    event_record_t *e = event_get_free();
113
    e->status = EVENT_PENDING;
114
    e->event = event;
115
    e->data = data;
116
    e->priority = priority;
117
    sysclock_get_time(&e->timestamp, NULL);
118
}
119
120
void event_setup(void) {
121
    for(uint8_t i=0; i<MAX_EVENTS; i++) {
122
        event_buffer[i].status = EVENT_FREE;
123
    }
124
    event_flags = 0;
125
126
    event_task = sched_task_create(event_task_fn, NULL, 30, 0, SCHED_ENABLED | SCHED_RUN_IDLE);
127
}
128