Statistics
| Revision:

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

History | View | Annotate | Download (10 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 "../init/scenariolist.h"
15
#include "../init/devicelist.h"
16
#include "../logics/device_threads.h"
17
//#include "../logics/scenario_threads.h"
18

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

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

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

    
49
int hciChanged = HCI_CHANGED_RESET;
50

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

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

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

    
72
    //umask(0);
73

    
74
    // Open any logs here
75

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
161
        pthread_exit(0);
162
}
163

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

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

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

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

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

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

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

    
225
                        shutDownLogic();
226
                    }
227

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

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

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

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

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

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

    
290
    //kill device threads
291
    while(hold)
292
    {
293
        pthread_cancel(hold->pthr_idx);
294
        hold=hold->nxt;
295
    }
296

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

    
306
    //free memory
307
    //printf("Freeing memory!\n");
308
    freeDeviceList(hDevice);
309
    freeScenarioList(hScenario);
310
    freeThreadIDList(hThrIDhold_dev);
311
    freeThreadIDList(hThrIDhold_scn);
312

    
313
    //reinit devices
314
    //printf("Reinitializing devices!\n");
315
    hDevice   = setDeviceList();
316

    
317
    //reinit scenarios
318
    //printf("Reinitializing scenarios!\n");
319
    hScenario = setNewScenarioList(hDevice);
320

    
321
    //restart main thread
322
    //printf("Restarting main thread!\n");
323
        pthread_create(&decisionMakingThread,NULL,decisionMakingThread_routine,NULL);
324

    
325
        return 1; //sucess, TODO add fail conditions
326
}
327

    
328
int shutDownLogic()
329
{
330
    thread_id_holder *hold;
331
    hold = hThrIDhold_dev;
332

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

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

    
350
    //free memory
351
    //printf("Freeing memory!\n");
352
    freeDeviceList(hDevice);
353
    freeScenarioList(hScenario);
354
    freeThreadIDList(hThrIDhold_dev);
355
    freeThreadIDList(hThrIDhold_scn);
356

    
357
    //stop main thread and HCI comm thread
358
    pthread_cancel(decisionMakingThread);
359
    pthread_cancel(hciConnectionThread);
360

    
361
        return 1; //sucess, TODO add fail conditions
362
}