1 #include <sancus/reactive.h>
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <random.h>
6
7 #include "wan_commands.h"
8
9 #define SMNAME ESME
10
11 #define MAX_OBSERVERS 4
12
13 SM_OUTPUT(SMNAME, load_switch_out);
14 SM_OUTPUT(SMNAME, central_system_out);
15 SM_OUTPUT(SMNAME, han_if_out);
16
17
18 static int SM_DATA(SMNAME) initialised;
19 static uint16_t SM_DATA(SMNAME) time;
20 static int SM_DATA(SMNAME) seq;
21
22 static uint8_t SM_DATA(SMNAME) supply_state;
23 static uint16_t SM_DATA(SMNAME) active_power_import;
24 static uint16_t SM_DATA(SMNAME) active_import_register;
25 static uint8_t SM_DATA(SMNAME) observers[MAX_OBSERVERS];
26
27 #define CHANNEL_LS 1
28 #define CHANNEL_CS 2
29 #define CHANNEL_HAN 3
30
31 static uint32_t modu16 (uint32_t i, uint32_t j)
32 {
33 return (i % j);
34 }
35
36 void SM_FUNC(SMNAME) init(void)
37 {
38 if (! initialised) {
39 time = 0;
40 seq = 0;
41
42 supply_state = 1;
43 active_power_import = 0;
44 active_import_register = 0;
45
46 random_init(0);
47 for (int i = 0; i < MAX_OBSERVERS; i++) {
48 observers[i] = 0 ;
49 }
50 observers[0] = CHANNEL_HAN;
51
52 initialised = 1;
53 }
54 }
55
56 void SM_FUNC(SMNAME) produce_output(uint8_t channel, uint8_t info)
57 {
58 uint8_t data[4] __attribute__((aligned(2)))
59 = { (seq >> (8*0)) & 0xff,
60 (seq >> (8*1)) & 0xff,
61 info, 0 };
62 seq += 1;
63
64 if (channel == CHANNEL_CS) {
65 central_system_out(data, sizeof(data));
66 }
67
68 if (channel == CHANNEL_LS) {
69 load_switch_out(data, sizeof(data));
70 }
71 }
72
73 void SM_FUNC(SMNAME) output_consumption_data(void)
74 {
75 uint8_t data[10] __attribute__((aligned(2)))
76 = { (seq >> (8*0)) & 0xff,
77 (seq >> (8*1)) & 0xff,
78 GET_CONSUMPTION_DATA, 0,
79 supply_state,
80 (active_power_import >> (8*0)) & 0xff,
81 (active_power_import >> (8*1)) & 0xff,
82 (active_import_register >> (8*0)) & 0xff,
83 (active_import_register >> (8*1)) & 0xff};
84
85 for (int i = 0; i < MAX_OBSERVERS; i++) {
86 if (observers[i] == CHANNEL_HAN) {
87 han_if_out(data, sizeof(data));
88 }
89 else if (observers[i] == CHANNEL_CS) {
90 central_system_out(data, sizeof(data));
91 }
92 }
93 }
94
95 void SM_FUNC(SMNAME) get_input(uint8_t channel, const uint8_t *data,
96 size_t len)
97 {
98 if (channel == CHANNEL_LS && len >= 3) {
99 supply_state = data[2];
100 }
101
102 if (channel == CHANNEL_CS && len >= 3) {
103 if (data[2] == GET_CONSUMPTION_DATA) {
104 for (int i = 0; i < MAX_OBSERVERS; i++) {
105 if (observers[i] == 0 || observers[i] == CHANNEL_CS) {
106 observers[i] = CHANNEL_CS;
107 produce_output(CHANNEL_CS, GET_CONSUMPTION_DATA);
108 break; }
109 }
110 }
111 }
112 }
113
114
115 SM_ENTRY(SMNAME) void advance_time(void)
116 {
117 if (! initialised) {
118 init();
119 produce_output(CHANNEL_LS, GET_SUPPLY_STATE);
120 }
121 time++;
122
123
124 if (supply_state == SUPPLY_STATE_ENABLED) {
125 active_power_import = 50 + (modu16(random_rand(), 100));
126 } else {
127 active_power_import = 0;
128 }
129
130 active_import_register += active_power_import;
131
132
133 if (! (modu16(time, 5))) {
134 produce_output(CHANNEL_LS, GET_SUPPLY_STATE);
135 output_consumption_data();
136 }
137 }
138
139 SM_INPUT(SMNAME, load_switch_in, data, len)
140 {
141 if (! initialised) { init(); }
142
143 get_input(CHANNEL_LS, data, len);
144 }
145
146 SM_INPUT(SMNAME, central_system_in, data, len)
147 {
148 if (! initialised) { init(); }
149
150 get_input(CHANNEL_CS, data, len);
151 }
152