Statistics
| Revision:

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

History | View | Annotate | Download (10.6 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 "../hci_comm/hciChanged.h"
12
#include "../hci_comm/hci_comm.h"
13
#include "../init/scenariolist.h"
14
#include "../init/devicelist.h"
15
#include "../logics/device_threads.h"
16
//#include "../logics/scenario_threads.h"
17

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

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

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

    
48
int hciChanged = HCI_CHANGED_RESET;
49

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

    
57
// Application entry point
58
int main(int argc, char *argv[]) {
59
    /** //DAEMON
60
    pid_t pid, sid;
61

62
    pid = fork();
63
    if (pid < 0) {
64
            exit(EXIT_FAILURE);
65
    }
66
    // EXIT PARENT
67
    if (pid > 0) {
68
            exit(EXIT_SUCCESS);
69
    }
70

71
    //umask(0);
72

73
    // Open any logs here
74

75
    // Create a new SID for the child process
76
    sid = setsid();
77
    if (sid < 0) {
78
            // Log the failure
79
            exit(EXIT_FAILURE);
80
    }
81

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

    
92
    printf("Devices present:\t%d\n",   getNumberOfDevices());
93
    printf("Scenarios present:\t%d\n", getNumberOfScenarios());
94

    
95
    /* regular work */
96
    //*
97
        pthread_create(&hciConnectionThread, NULL,hciConnectionThread_routine, NULL);
98
        pthread_create(&decisionMakingThread,NULL,decisionMakingThread_routine,NULL);
99

    
100
        pthread_join(hciConnectionThread,NULL);
101
        //pthread_join(decisionMakingThread,NULL);
102
    /**/
103
        exit(0);
104
}
105

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

    
111
    /**dummy threads for input devices (sensors)**/
112
    hThrIDhold_dev = NULL;
113
    thread_id_holder *t_holder, *t_holder_old; //just for list of IDs creation, for both scenarios and devices
114
    t_holder_old = NULL;
115

    
116
    int i;
117
    for(i=0; i<getNumberOfDevices(); i++)
118
    {
119
        t_holder = (thread_id_holder *)malloc(sizeof(thread_id_holder));
120
        pthread_create(&t_holder->pthr_idx,NULL,randomValThread_routine,NULL);
121

    
122
        t_holder->nxt=NULL;
123
        if(t_holder_old!=NULL)
124
            t_holder_old->nxt=t_holder;
125
        t_holder_old=t_holder;
126

    
127
        if(hThrIDhold_dev==NULL)
128
            hThrIDhold_dev=t_holder_old;
129
    }
130

    
131
    /**start scenario threads**/
132
    t_holder_old = NULL;
133
    hThrIDhold_scn=NULL;
134

    
135
    for(i=0; i<getNumberOfScenarios(); i++)
136
    {
137
        t_holder = (thread_id_holder *)malloc(sizeof(thread_id_holder));
138
        pthread_create(&t_holder->pthr_idx,NULL,scenarioThread_routine,NULL);
139

    
140
        t_holder->nxt=NULL;
141
        if(t_holder_old!=NULL)
142
            t_holder_old->nxt=t_holder;
143
        t_holder_old=t_holder;
144

    
145
        if(hThrIDhold_scn==NULL)
146
            hThrIDhold_scn=t_holder_old;
147
    }
148

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

    
154
// HCI connection thread routine
155
// Start listening to some port
156
void *hciConnectionThread_routine(void *dummy) {
157
    printf("hciConnectionThread_routine started\n");
158
        int hciErrorCode = listenTo(1100);
159

    
160
        pthread_exit(0);
161
}
162

    
163
// scenario thread routine
164
void *scenarioThread_routine(void *dummy)
165
{
166
    scenario *scen;
167
    device   *inDev;
168
    int      active = 0;
169
    float    scenarioBuffer;
170
    //printf("My scen ID> %ld\n",pthread_self());
171

    
172
    /*load scenario*/
173
    scen = getAvailableScenario(hScenario);
174
    if(!scen) pthread_exit(0);
175

    
176
    // TODO add pointer to this device (all of them actually) to scenario structure - problems with segfault
177
    //indev = scen->inDev;
178
    inDev = getDevice(hDevice, scen->inDevice_id);
179
    scen->buf=inDev->buf;
180
    printf("Scenario %s buffer updated to %.2f!\n", scen->scen_id, inDev->buf);
181
    //set its value
182
    //*
183
    while(1) //TODO signal == true
184
    {
185
        /// main scenario loop
186
        //printf("inDev->buf %.2f\n", 1.0f*inDev->buf);
187
        if(active)
188
            sleep(scen->actvChkItv);
189
        else
190
            sleep(scen->idleChkItv);
191
        //checking primary condition
192
        if(scen->buf) // is not null
193
        {
194
            scen->buf = scen->buf*scen->alpha+inDev->buf*(1-scen->alpha);
195
            //printf("Scenario %s buffer updated to %f, alpha: %.2f!\n", scen->scen_id, scenarioBuffer, scen->alpha);
196
            syslog(LOG_MAIL, "%s:%.2f", scen->inDevice_id, scen->buf);
197
            active = 1;
198

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

    
207
                    /// Forking to execute action!
208
                    pid_t pid, sid;
209

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

    
221
                        execl(scen->action, power);
222
                        printf("Zaganjam napravo %s z mocjo %d\n", scen->scen_id, power);
223

    
224
                        shutDownLogic();
225
                    }
226

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

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

    
263
void freeDeviceList(device *dev)
264
{
265
    if(dev->nxt!=NULL)
266
        freeDeviceList(dev->nxt);
267
    free(dev);
268
}
269

    
270
void freeScenarioList(scenario *scn)
271
{
272
    if(scn->nxt!=NULL)
273
        freeScenarioList(scn->nxt);
274
    free(scn);
275
}
276

    
277
void freeThreadIDList(thread_id_holder *tih)
278
{
279
    if(tih->nxt!=NULL)
280
        freeThreadIDList(tih->nxt);
281
    free(tih);
282
}
283

    
284
int reinitialiseLogic()
285
{
286
    thread_id_holder *hold;
287
    hold = hThrIDhold_dev;
288
    //hThrIDhold_dev = NULL;
289

    
290
    //kill device threads
291
    printf("Attempting to cancel threads!\n");
292
    while(hold)
293
    {
294
        printf("Cancelling dev thread %ld with return state %d\n", hold->pthr_idx,pthread_cancel(hold->pthr_idx));
295
        //TODO free thread_id_holder list too!
296
        hold=hold->nxt;
297
    }
298

    
299
    //kill scenario threads
300
    hold = hThrIDhold_scn;
301
    //hThrIDhold_scn = NULL;
302
    while(hold)
303
    {
304
        printf("Cancelling scn thread %ld with return state %d\n", hold->pthr_idx,pthread_cancel(hold->pthr_idx));
305
        //TODO free thread_id_holder list too!
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
    //hThrIDhold_dev = NULL;
336

    
337
    //kill device threads
338
    printf("Attempting to cancel threads!\n");
339
    while(hold)
340
    {
341
        printf("Cancelling dev thread %ld with return state %d\n", hold->pthr_idx,pthread_cancel(hold->pthr_idx));
342
        //TODO free thread_id_holder list too!
343
        hold=hold->nxt;
344
    }
345

    
346
    //kill scenario threads
347
    hold = hThrIDhold_scn;
348
    //hThrIDhold_scn = NULL;
349
    while(hold)
350
    {
351
        printf("Cancelling scn thread %ld with return state %d\n", hold->pthr_idx,pthread_cancel(hold->pthr_idx));
352
        //TODO free thread_id_holder list too!
353
        hold=hold->nxt;
354
    }
355

    
356
    //free memory
357
    printf("Freeing memory!\n");
358
    freeDeviceList(hDevice);
359
    freeScenarioList(hScenario);
360
    freeThreadIDList(hThrIDhold_dev);
361
    freeThreadIDList(hThrIDhold_scn);
362

    
363
    //stop main thread and HCI comm thread
364
    pthread_cancel(decisionMakingThread);
365
    pthread_cancel(hciConnectionThread);
366

    
367
        return 1; //sucess, TODO add fail conditions
368
}