Statistics
| Revision:

root / logic / trunk / src / startup / main.c @ 71

History | View | Annotate | Download (10.1 KB)

1
/*
2
 * main.c
3
 *
4
 * 2011, Aleksander Besir (alex.besir@gmail.com)
5
 *
6
 */
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <pthread.h>
10
#include <syslog.h>
11
#include <unistd.h>
12
#include "../hci_comm/hciChanged.h"
13
#include "../hci_comm/hci_comm.h"
14
#include "../drv_comm/drv_comm.h"
15
#include "../init/scenariolist.h"
16
#include "../init/devicelist.h"
17
#include "../logics/device_threads.h"
18
//#include "../logics/scenario_threads.h"
19

    
20
// Inter-thread shared variables
21
// TODO: These variables could be configuration variables
22
//       (eg: static boolean loggingEnabled)
23
static device           *hDevice;       //device list
24
static scenario         *hScenario;     //scenario list
25
static thread_id_holder *hThrIDhold_dev;//holds IDs of running threads (devices)
26
static thread_id_holder *hThrIDhold_scn;//holds IDs of running threads (scenarios)
27
//extern scenario *test;   //device list
28

    
29
// Crtitical section mutual exclusion security
30
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
31
pthread_t       decisionMakingThread;
32
pthread_t       hciConnectionThread;
33

    
34
// Global variable to check, if HCI made any changes that need
35
// to be updated by the logic.
36
// Changing this variable's value must be done using the
37
// mutex mtx declared before.
38
// To change variables value you should do this:
39
//    pthread_mutex_lock(&mtx);
40
//    hciChanged = 0;
41
//    pthread_mutex_unlock(&mtx);
42
// The meaning of hciChanged possible values is in hci_comm/hciChanged.h.
43
// HCI should always reset hciChanged value to HCI_CHANGED_RESET after
44
// checking it's value.
45
// To use mtx and hciChanged variables in other .c files, write
46
//    extern int hciChanged;
47
//    extern pthread_mutex_t mtx;
48
// on top of the class.
49

    
50
int hciChanged = HCI_CHANGED_RESET;
51

    
52
void *decisionMakingThread_routine(void *dummy);
53
void *hciConnectionThread_routine(void *dummy);
54
void *randomValThread_routine(void *dummy);
55
void *scenarioThread_routine(void *dummy);
56
int  reinitialiseLogic(); // on HCI request
57
int  shutDownLogic();
58

    
59
// devices
60
const char *dev1="/dev/dev_thermometer_01";
61
// Application entry point
62
int main(int argc, char *argv[]) {
63
    /** //DAEMON
64
    pid_t pid, sid;
65

66
    pid = fork();
67
    if (pid < 0) {
68
            exit(EXIT_FAILURE);
69
    }
70
    // EXIT PARENT
71
    if (pid > 0) {
72
            exit(EXIT_SUCCESS);
73
    }
74

75
    //umask(0);
76

77
    // Open any logs here
78

79
    // Create a new SID for the child process
80
    sid = setsid();
81
    if (sid < 0) {
82
            // Log the failure
83
            exit(EXIT_FAILURE);
84
    }
85

86
    // Close out the standard file descriptors
87
    // Because daemons generally dont interact directly with user so there is no need of keeping these open
88
    close(STDIN_FILENO);
89
    close(STDOUT_FILENO);
90
    close(STDERR_FILENO);
91
    /**/
92
    /* initialisation */
93
    hDevice   = setDeviceList();
94
    hScenario = setNewScenarioList(hDevice);
95

    
96
    printf("Devices present:\t%d\n",   getNumberOfDevices());
97
    printf("Scenarios present:\t%d\n", getNumberOfScenarios());
98

    
99
    /* regular work */
100
    //*
101
        pthread_create(&hciConnectionThread, NULL,hciConnectionThread_routine, NULL);
102
        pthread_create(&decisionMakingThread,NULL,decisionMakingThread_routine,NULL);
103

    
104
        pthread_join(hciConnectionThread,NULL);
105
        //pthread_join(decisionMakingThread,NULL);
106
    /**/
107
        exit(0);
108
}
109

    
110
// Decision-making thread routine
111
// Should just call a function that implements decision making module of the logic
112
void *decisionMakingThread_routine(void *dummy) {
113
    printf("-- decisionMakingThread_routine started --\n");
114

    
115
    /**dummy threads for input devices (sensors)**/
116
    hThrIDhold_dev = NULL;
117
    thread_id_holder *t_holder, *t_holder_old; //just for list of IDs creation, for both scenarios and devices
118
    t_holder_old = NULL;
119

    
120
    int i;
121
    for(i=0; i<getNumberOfDevices(); i++)
122
    {
123
        t_holder = (thread_id_holder *)malloc(sizeof(thread_id_holder));
124
        pthread_create(&t_holder->pthr_idx,NULL,randomValThread_routine,NULL);
125

    
126
        t_holder->nxt=NULL;
127
        if(t_holder_old!=NULL)
128
            t_holder_old->nxt=t_holder;
129
        t_holder_old=t_holder;
130

    
131
        if(hThrIDhold_dev==NULL)
132
            hThrIDhold_dev=t_holder_old;
133
    }
134

    
135
    /**start scenario threads**/
136
    t_holder_old = NULL;
137
    hThrIDhold_scn=NULL;
138

    
139
    for(i=0; i<getNumberOfScenarios(); i++)
140
    {
141
        t_holder = (thread_id_holder *)malloc(sizeof(thread_id_holder));
142
        pthread_create(&t_holder->pthr_idx,NULL,scenarioThread_routine,NULL);
143

    
144
        t_holder->nxt=NULL;
145
        if(t_holder_old!=NULL)
146
            t_holder_old->nxt=t_holder;
147
        t_holder_old=t_holder;
148

    
149
        if(hThrIDhold_scn==NULL)
150
            hThrIDhold_scn=t_holder_old;
151
    }
152

    
153
    /*start some sort of control over scenarios? - hmm morda ne...bom jutri :)*/
154
    //printf("Exiting main thread\n");
155
        pthread_exit(0);
156
}
157

    
158
// HCI connection thread routine
159
// Start listening to some port
160
void *hciConnectionThread_routine(void *dummy) {
161
    printf("hciConnectionThread_routine started\n");
162
        int hciErrorCode = listenTo(1100);
163

    
164
        pthread_exit(0);
165
}
166

    
167
// scenario thread routine
168
void *scenarioThread_routine(void *dummy)
169
{
170
    scenario *scen;
171
    device   *inDev;
172
    int      active = 0;
173
    //printf("My scen ID> %ld\n",pthread_self());
174

    
175
    /*load scenario*/
176
    scen = getAvailableScenario(hScenario);
177
    if(!scen) pthread_exit(0);
178

    
179
    // TODO add pointer to this device (all of them actually) to scenario structure - problems with segfault
180
    //indev = scen->inDev;
181
    inDev = getDevice(hDevice, scen->inDevice_id);
182
    scen->buf=inDev->buf/10; //TODO make sure buffer values make sense!
183
    //printf("Scenario %s buffer updated to %.2f!\n", scen->scen_id, inDev->buf/10);
184
    //set its value
185
    //*
186
    while(1) //TODO signal == true
187
    {
188
        /// main scenario loop
189
        //printf("inDev->buf %.2f\n", 1.0f*inDev->buf);
190
        printf("scen->buf %.2f\n", 1.0f*scen->buf);
191
        if(active)
192
            sleep(scen->actvChkItv);
193
        else
194
            sleep(scen->idleChkItv);
195

    
196
        //checking primary condition
197
        scen->buf = scen->buf*scen->alpha+inDev->buf*(1-scen->alpha)/10;
198
        //printf("Scenario %s buffer updated to %.2f, alpha: %.2f!\n", scen->scen_id, scen->buf, scen->alpha);
199
        syslog(LOG_MAIL, "%s:%.2f", scen->inDevice_id, scen->buf);
200
        active = 1;
201

    
202
        if((scen->buf > scen->optval + scen->tolval) ||
203
           (scen->buf < scen->optval - scen->tolval))
204
        {
205
            if(evaluateAdditionalConditions(scen->cond_l, hDevice))
206
            {
207
                // TODO syslog - "action:scen_ID:power_percentage"
208
                int power = getPowerPercentage(scen->minval, scen->maxval, scen->optval, &scen->buf, scen->func);
209

    
210
                /// Forking to execute action!
211
                pid_t pid;
212

    
213
                pid = fork();
214
                if (pid < 0) {
215
                        exit(EXIT_FAILURE);
216
                }
217
                // ignore parent
218
                if (pid > 0) {
219
                }
220
                else
221
                {
222
                    /*TODO execute action with parameter(s)*/
223
                    syslog(LOG_MAIL, "%s:%s:%.2f", scen->action, scen->scen_id, power);
224

    
225
                    execl(scen->action, power);
226
                    printf("Zaganjam napravo %s z mocjo %d\n", scen->scen_id, power);
227

    
228
                    shutDownLogic();
229
                }
230

    
231
            }
232
            else
233
                printf("Scenario %s not updated, additional conditions false!\n", scen->scen_id);
234
        }
235
        else
236
            active = 0;
237
        /*
238
        if(active)
239
            printf("%s main buffer %.2f, sleeping %d\n",scen->scen_id, scen->buf, scen->actvChkItv);
240
        else
241
            printf("%s main buffer %.2f, sleeping %d\n",scen->scen_id, scen->buf, scen->idleChkItv);
242
        /**/
243
    }
244
    /**/
245
           pthread_exit(0);
246
}
247

    
248
void *randomValThread_routine(void *dummy)
249
{
250
    //get device
251
    device *dev;
252
    dev = getAvailableDevice(hDevice);
253
    if(dev){}
254
    else
255
        pthread_exit(0);
256
    //set its value
257
    while(1) //TODO signal == true
258
    {
259
        dev->buf=get_device_value(dev1);
260
        //dev->buf=random()%10+20;// random 20-30
261
        //printf("device %s buf = %d\n", dev->id, dev->buf);
262
        sleep(dev->readitv);
263
    }
264
           pthread_exit(0);
265
}
266

    
267
void freeDeviceList(device *dev)
268
{
269
    if(dev->nxt!=NULL)
270
        freeDeviceList(dev->nxt);
271
    free(dev);
272
}
273

    
274
void freeScenarioList(scenario *scn)
275
{
276
    if(scn->nxt!=NULL)
277
        freeScenarioList(scn->nxt);
278
    free(scn);
279
}
280

    
281
void freeThreadIDList(thread_id_holder *tih)
282
{
283
    if(tih->nxt!=NULL)
284
        freeThreadIDList(tih->nxt);
285
    free(tih);
286
}
287

    
288
int reinitialiseLogic()
289
{
290
    thread_id_holder *hold;
291
    hold = hThrIDhold_dev;
292

    
293
    //kill device threads
294
    while(hold)
295
    {
296
        pthread_cancel(hold->pthr_idx);
297
        hold=hold->nxt;
298
    }
299

    
300
    //kill scenario threads
301
    hold = hThrIDhold_scn;
302
    //hThrIDhold_scn = NULL;
303
    while(hold)
304
    {
305
        pthread_cancel(hold->pthr_idx);
306
        hold=hold->nxt;
307
    }
308

    
309
    //free memory
310
    //printf("Freeing memory!\n");
311
    freeDeviceList(hDevice);
312
    freeScenarioList(hScenario);
313
    freeThreadIDList(hThrIDhold_dev);
314
    freeThreadIDList(hThrIDhold_scn);
315

    
316
    //reinit devices
317
    //printf("Reinitializing devices!\n");
318
    hDevice   = setDeviceList();
319

    
320
    //reinit scenarios
321
    //printf("Reinitializing scenarios!\n");
322
    hScenario = setNewScenarioList(hDevice);
323

    
324
    //restart main thread
325
    //printf("Restarting main thread!\n");
326
        pthread_create(&decisionMakingThread,NULL,decisionMakingThread_routine,NULL);
327

    
328
        return 1; //sucess, TODO add fail conditions
329
}
330

    
331
int shutDownLogic()
332
{
333
    thread_id_holder *hold;
334
    hold = hThrIDhold_dev;
335

    
336
    //kill device threads
337
    //printf("Attempting to cancel threads!\n");
338
    while(hold)
339
    {
340
        pthread_cancel(hold->pthr_idx);
341
        hold=hold->nxt;
342
    }
343

    
344
    //kill scenario threads
345
    hold = hThrIDhold_scn;
346
    while(hold)
347
    {
348
        pthread_cancel(hold->pthr_idx);
349
        //TODO free thread_id_holder list too!
350
        hold=hold->nxt;
351
    }
352

    
353
    //free memory
354
    //printf("Freeing memory!\n");
355
    freeDeviceList(hDevice);
356
    freeScenarioList(hScenario);
357
    freeThreadIDList(hThrIDhold_dev);
358
    freeThreadIDList(hThrIDhold_scn);
359

    
360
    //stop main thread and HCI comm thread
361
    pthread_cancel(decisionMakingThread);
362
    pthread_cancel(hciConnectionThread);
363

    
364
        return 1; //sucess, TODO add fail conditions
365
}