15
15
#include "chainlib.h"
16
16
#include "chainevent.h"
17
17
#include "chainworker.h"
18
+ #include "chainmath.h"
19
+ #include "chainquery.h"
18
20
19
21
typedef struct chain_device
20
22
{
21
23
t_chain_worker s_worker ;
22
24
t_symbol * s_device_name ;
23
25
long s_autoupdate ;
26
+ long s_deviation ;
24
27
void * s_outlet ;
25
28
void * s_outlet2 ;
26
29
} t_chain_device ;
@@ -76,6 +79,7 @@ int C74_EXPORT main(void)
76
79
CLASS_ATTR_ACCESSORS (c , "device_name" , NULL , (method )chain_device_set_device_name );
77
80
78
81
CLASS_ATTR_LONG (c , "autoupdate" , 0 , t_chain_device , s_autoupdate );
82
+ CLASS_ATTR_LONG (c , "deviation" , 0 , t_chain_device , s_deviation );
79
83
80
84
class_register (CLASS_BOX , c );
81
85
s_chain_device_class = c ;
@@ -97,6 +101,7 @@ void *chain_device_new(t_symbol *s, long argc, t_atom *argv)
97
101
x -> s_outlet2 = outlet_new (x , NULL );
98
102
x -> s_outlet = outlet_new (x , NULL );
99
103
x -> s_autoupdate = 1 ;
104
+ x -> s_deviation = 0 ;
100
105
101
106
attr_args_process (x , argc , argv );
102
107
@@ -154,6 +159,23 @@ void chain_device_send_sensor(t_chain_device *x, const char *href){
154
159
outlet_list (x -> s_outlet , 0L , ac , av );
155
160
}
156
161
162
+ double chain_device_compute_deviation (t_chain_device * x , t_symbol * metric ,
163
+ double value )
164
+ {
165
+ t_db_result * db_result = NULL ;
166
+ query_data_by_metric_name (x -> s_worker .s_db , metric -> s_name , & db_result );
167
+
168
+ long numrecords = db_result_numrecords (db_result );
169
+ double values [numrecords ];
170
+ for (long i = 0 ; i < numrecords ; i ++ ){
171
+ values [i ] = db_result_float (db_result , i , 0 );
172
+ }
173
+ double mean = chain_mean (values , numrecords );
174
+ double std = chain_std (values , numrecords );
175
+
176
+ return (value - mean ) / std ;
177
+ }
178
+
157
179
void chain_device_send_metric (t_chain_device * x , t_symbol * metric ){
158
180
if (!x -> s_worker .s_db ){
159
181
chain_error ("No DB!" );
@@ -177,6 +199,10 @@ void chain_device_send_metric(t_chain_device *x, t_symbol *metric){
177
199
double value = db_result_float (db_result , 0 , 0 );
178
200
const char * timestamp = db_result_string (db_result , 0 , 1 );
179
201
202
+ if (x -> s_deviation ){
203
+ value = chain_device_compute_deviation (x , metric , value );
204
+ }
205
+
180
206
t_atom av [2 ];
181
207
short ac = 2 ;
182
208
atom_setsym (av , metric );
@@ -208,10 +234,15 @@ void chain_device_send_all(t_chain_device *x){
208
234
timestamp = db_result_string (db_result , i , 1 );
209
235
value = db_result_float (db_result , i , 0 );
210
236
metric_name = db_result_string (db_result , i , 2 );
237
+ t_symbol * metric = gensym (metric_name );
238
+
239
+ if (x -> s_deviation ){
240
+ value = chain_device_compute_deviation (x , metric , value );
241
+ }
211
242
212
243
t_atom av [2 ];
213
244
short ac = 2 ;
214
- atom_setsym (av , gensym ( metric_name ) );
245
+ atom_setsym (av , metric );
215
246
atom_setfloat (av + 1 , value );
216
247
217
248
outlet_list (x -> s_outlet , 0L , ac , av );
@@ -328,7 +359,11 @@ void chain_device_data(t_chain_device *x, t_symbol *metric, long start, long end
328
359
329
360
t_atom av [num_events ];
330
361
for (int i = 0 ; i < num_events ; i ++ ){
331
- atom_setfloat (av + i , (events + i )-> s_value );
362
+ double value = (events + i )-> s_value ;
363
+ if (x -> s_deviation ){
364
+ value = chain_device_compute_deviation (x , metric , value );
365
+ }
366
+ atom_setfloat (av + i , value );
332
367
}
333
368
outlet_anything (x -> s_outlet , metric , num_events , av );
334
369
free (events );
0 commit comments