Revision 10

View differences:

logic/trunk/src/hci_comm/hci_comm.h
1
/*
2
 * hci_comm.h
3
 *
4
 * 2011, Aleksander Besir (alex.besir@gmail.com)
5
 *
6
 */
7
 
8
 #ifndef _ENERAPTOR_HCI_COMM
9
 #define _ENERAPTOR_HCI_COMM
10
 
11
 // Error codes
12
 #define HCI_COMM_TERMINATED_BY_LOGIC  0 // Terminated by logic
13
 #define HCI_COMM_ERR_NEW_SOCKET_FAIL -1 // Cannot create new socket
14
 #define HCI_COMM_ERR_BIND_FAIL       -2 // Cannot bind socket to port
15
 #define HCI_COMM_ERR_LISTEN_FAIL     -3 // Cannot listen to port
16
 #define HCI_COMM_ERR_ACCEPT_FAIL     -4 // Cannot accept request
17
 #define HCI_COMM_ERR_READ_FAIL       -5 // Cannot read request
18
 #define HCI_COMM_ERR_WRITE_FAIL      -6 // Cannot write response
19
 #define HCI_COMM_ERR_BUF_ALOC_FAIL  -99 // Cannot alocate memory for buffer
20
 
21
 // Program codes
22
 #define HCI_COMM_TERMINATE           -1 // Terminates the infinite listening loop
23
 
24
 // Constants
25
 #define HCI_COMM_REQUEST_BUFFER_SIZE  1024 // Bufer size in bytes
26
   // TODO: buffer size should be bigger!
27

  
28
 int listenTo(unsigned short int portNum);
29
 
30
 #endif
1
/*
2
 * hci_comm.h
3
 *
4
 * 2011, Aleksander Besir (alex.besir@gmail.com)
5
 *
6
 */
7

  
8
 #ifndef _ENERAPTOR_HCI_COMM
9
 #define _ENERAPTOR_HCI_COMM
10

  
11
 // Error codes
12
 #define HCI_COMM_TERMINATED_BY_LOGIC  0 // Terminated by logic
13
 #define HCI_COMM_ERR_NEW_SOCKET_FAIL -1 // Cannot create new socket
14
 #define HCI_COMM_ERR_BIND_FAIL       -2 // Cannot bind socket to port
15
 #define HCI_COMM_ERR_LISTEN_FAIL     -3 // Cannot listen to port
16
 #define HCI_COMM_ERR_ACCEPT_FAIL     -4 // Cannot accept request
17
 #define HCI_COMM_ERR_READ_FAIL       -5 // Cannot read request
18
 #define HCI_COMM_ERR_WRITE_FAIL      -6 // Cannot write response
19
 #define HCI_COMM_ERR_BUF_ALOC_FAIL  -99 // Cannot alocate memory for buffer
20

  
21
 // Program codes
22
 #define HCI_COMM_TERMINATE           -1 // Terminates the infinite listening loop
23

  
24
 // Constants
25
 #define HCI_COMM_REQUEST_BUFFER_SIZE  1024 // Bufer size in bytes
26
   // TODO: buffer size should be bigger!
27

  
28
 int listenTo(unsigned short int portNum);
29

  
30
 #endif
logic/trunk/src/hci_comm/hci_comm_listener.c
1
/*
2
 * hci_comm_listener.c
3
 *
4
 * 2011, Aleksander Besir (alex.besir@gmail.com)
5
 *
6
 */
7

  
8
#include "hci_comm.h"
9
#include <sys/types.h>
10
#include <sys/socket.h>
11
#include <netinet/in.h>
12
#include <arpa/inet.h>
13
#include <stdio.h>
14
#include <stdlib.h>
15
#include <string.h>
16
#include <unistd.h>
17

  
18
int listenTo(unsigned short int portNum) {
19
	
20
	// Buffer
21
	char *requestBuffer = malloc(HCI_COMM_REQUEST_BUFFER_SIZE * sizeof(char));
22
	if(requestBuffer == NULL) {
23
		fprintf(stderr,"HCI comm error: Cannot allocate buffer.\n");
24
		return HCI_COMM_ERR_BUF_ALOC_FAIL;
25
	}
26
	
27
	// Socket holder
28
	int socketHolder = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
29
	if(socketHolder < 0) {
30
		fprintf(stderr,"HCI comm error: Cannot create a new socket.\n");
31
		return HCI_COMM_ERR_NEW_SOCKET_FAIL;
32
	}
33
	
34
	// Socket address holder
35
	struct sockaddr_in socketAddressHolder;
36
	memset(&socketAddressHolder, 0, sizeof(socketAddressHolder));
37
	socketAddressHolder.sin_family      = AF_INET;
38
    	socketAddressHolder.sin_port        = htons(portNum);
39
    	socketAddressHolder.sin_addr.s_addr = INADDR_ANY;
40

  
41
	// Bind socket to port
42
	int bindingResult = bind(socketHolder,(struct sockaddr *)&socketAddressHolder, sizeof(socketAddressHolder));
43
	if(bindingResult == -1) {
44
		fprintf(stderr,"HCI comm error: Cannot bind socket to port %d.\n",portNum);
45
		close(socketHolder);
46
		return HCI_COMM_ERR_BIND_FAIL;
47
	}
48
	
49
	// Listen to port
50
	int listenResult = listen(socketHolder, 10);
51
	if(listenResult == -1) {
52
		fprintf(stderr,"HCI comm error: Cannot listen to port %d.\n",portNum);
53
		close(socketHolder);
54
		return HCI_COMM_ERR_LISTEN_FAIL;
55
	}
56
	
57
	// Infinite listening
58
	while(1) {
59
		
60
		// Accept request
61
		int connectionHolder = accept(socketHolder,NULL,NULL);
62
		if(connectionHolder < 0) {
63
			fprintf(stderr,"HCI comm error: Error accepting request.\n");
64
			close(socketHolder);
65
			return HCI_COMM_ERR_ACCEPT_FAIL;
66
		}
67
		
68
		// Read request
69
		int readResult = read(connectionHolder,requestBuffer,HCI_COMM_REQUEST_BUFFER_SIZE);
70
		if(readResult < 0) {
71
			fprintf(stderr,"HCI comm error: Error reading request.\n");
72
			close(socketHolder);
73
			return HCI_COMM_ERR_READ_FAIL;
74
		}
75
		
76
		// Create a response
77
		char *hciResponse = "Works!"; // TODO
78
		int responseLength = 6; // TODO
79
		
80
		// Check if logic wants to terminate the infinite loop
81
		if(responseLength == HCI_COMM_TERMINATE) {
82
			break;
83
		}
84
		
85
		// Send response
86
		int writeResult = write(connectionHolder,hciResponse,responseLength);
87
		if(writeResult < 0) {
88
			fprintf(stderr,"HCI comm error: Error writting response.\n");
89
			close(socketHolder);
90
			return HCI_COMM_ERR_WRITE_FAIL;
91
		}
92
		
93
	}
94
	
95
	// Terminate
96
	close(socketHolder);
97
	free(requestBuffer);
98
	requestBuffer = NULL;
99
	return HCI_COMM_TERMINATED_BY_LOGIC;
100

  
101
}
1
/*
2
 * hci_comm_listener.c
3
 *
4
 * 2011, Aleksander Besir (alex.besir@gmail.com)
5
 *
6
 */
7

  
8
#include "hci_comm.h"
9
#include <sys/types.h>
10
#include <sys/socket.h>
11
#include <netinet/in.h>
12
#include <arpa/inet.h>
13
#include <stdio.h>
14
#include <stdlib.h>
15
#include <string.h>
16
#include <unistd.h>
17

  
18
int listenTo(unsigned short int portNum) {
19

  
20
	// Buffer
21
	char *requestBuffer = malloc(HCI_COMM_REQUEST_BUFFER_SIZE * sizeof(char));
22
	if(requestBuffer == NULL) {
23
		fprintf(stderr,"HCI comm error: Cannot allocate buffer.\n");
24
		return HCI_COMM_ERR_BUF_ALOC_FAIL;
25
	}
26

  
27
	// Socket holder
28
	int socketHolder = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
29
	if(socketHolder < 0) {
30
		fprintf(stderr,"HCI comm error: Cannot create a new socket.\n");
31
		return HCI_COMM_ERR_NEW_SOCKET_FAIL;
32
	}
33

  
34
	// Socket address holder
35
	struct sockaddr_in socketAddressHolder;
36
	memset(&socketAddressHolder, 0, sizeof(socketAddressHolder));
37
	socketAddressHolder.sin_family      = AF_INET;
38
    	socketAddressHolder.sin_port        = htons(portNum);
39
    	socketAddressHolder.sin_addr.s_addr = INADDR_ANY;
40

  
41
	// Bind socket to port
42
	int bindingResult = bind(socketHolder,(struct sockaddr *)&socketAddressHolder, sizeof(socketAddressHolder));
43
	if(bindingResult == -1) {
44
		fprintf(stderr,"HCI comm error: Cannot bind socket to port %d.\n",portNum);
45
		close(socketHolder);
46
		return HCI_COMM_ERR_BIND_FAIL;
47
	}
48

  
49
	// Listen to port
50
	int listenResult = listen(socketHolder, 10);
51
	if(listenResult == -1) {
52
		fprintf(stderr,"HCI comm error: Cannot listen to port %d.\n",portNum);
53
		close(socketHolder);
54
		return HCI_COMM_ERR_LISTEN_FAIL;
55
	}
56

  
57
	// Infinite listening
58
	while(1) {
59

  
60
		// Accept request
61
		int connectionHolder = accept(socketHolder,NULL,NULL);
62
		if(connectionHolder < 0) {
63
			fprintf(stderr,"HCI comm error: Error accepting request.\n");
64
			close(socketHolder);
65
			return HCI_COMM_ERR_ACCEPT_FAIL;
66
		}
67

  
68
		// Read request
69
		int readResult = read(connectionHolder,requestBuffer,HCI_COMM_REQUEST_BUFFER_SIZE);
70
		if(readResult < 0) {
71
			fprintf(stderr,"HCI comm error: Error reading request.\n");
72
			close(socketHolder);
73
			return HCI_COMM_ERR_READ_FAIL;
74
		}
75

  
76
		// Create a response
77
		char *hciResponse = "Works!"; // TODO
78
		int responseLength = 6; // TODO
79

  
80
		// Check if logic wants to terminate the infinite loop
81
		if(responseLength == HCI_COMM_TERMINATE) {
82
			break;
83
		}
84

  
85
		// Send response
86
		int writeResult = write(connectionHolder,hciResponse,responseLength);
87
		if(writeResult < 0) {
88
			fprintf(stderr,"HCI comm error: Error writting response.\n");
89
			close(socketHolder);
90
			return HCI_COMM_ERR_WRITE_FAIL;
91
		}
92

  
93
	}
94

  
95
	// Terminate
96
	close(socketHolder);
97
	free(requestBuffer);
98
	requestBuffer = NULL;
99
	return HCI_COMM_TERMINATED_BY_LOGIC;
100

  
101
}
logic/trunk/src/startup/main.c
1
/*
2
 * main.c
3
 *
4
 * 2011, Aleksander Besir (alex.besir@gmail.com)
5
 *
6
 */
7
 
8
#include "../hci_comm/hci_comm.h"
9
#include <stdio.h>
10
#include <pthread.h>
11

  
12
// Inter-thread shared variables
13
// TODO: These variables could be configuration variables
14
//       (eg: static boolean loggingEnabled)
15

  
16
// Crtitical section mutual exclusion security
17
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
18

  
19
// Application entry point
20
int main(int argc, char *argv[]) {
21

  
22
	pthread_t hciConnectionThread;
23
	pthread_t decisionMakingThread;
24
	
25
	pthread_create(&hciConnectionThread,NULL,hciConnectionThread_routine,NULL);
26
	pthread_create(&decisionMakingThread,NULL,decisionMakingThread_routine,NULL);
27
	
28
	pthread_join(hciConnectionThread,NULL);
29
	pthread_join(decisionMakingThread,NULL);
30
	
31
	exit(0);
32

  
33
}
34

  
35
// Decision-making thread routine
36
// Should just call a function that implements decision making module of the logic
37
void *decisionMakingThread_routine(void *dummy) {
38
	
39
	// TODO: Implemet decision making
40
	
41
	pthread_exit(0);
42
	
43
}
44

  
45
// HCI connection thread routine
46
// Start listening to some port
47
void *hciConnectionThread_routine(void *dummy) {
48

  
49
	int hciErrorCode = listenTo(1100);
50
	
51
	pthread_exit(0);
52

  
53
}
1
/*
2
 * main.c
3
 *
4
 * 2011, Aleksander Besir (alex.besir@gmail.com)
5
 *
6
 */
7

  
8
#include "../hci_comm/hci_comm.h"
9
#include <stdio.h>
10
#include <pthread.h>
11

  
12
// Inter-thread shared variables
13
// TODO: These variables could be configuration variables
14
//       (eg: static boolean loggingEnabled)
15

  
16
// Crtitical section mutual exclusion security
17
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
18

  
19
void *decisionMakingThread_routine(void *dummy);
20
void *hciConnectionThread_routine(void *dummy);
21

  
22
// Application entry point
23
int main(int argc, char *argv[]) {
24

  
25
    printf("Hello world!\n");
26

  
27
    setDeviceList();
28

  
29
	pthread_t hciConnectionThread;
30
	pthread_t decisionMakingThread;
31

  
32
	pthread_create(&hciConnectionThread,NULL,hciConnectionThread_routine,NULL);
33
	pthread_create(&decisionMakingThread,NULL,decisionMakingThread_routine,NULL);
34

  
35
	pthread_join(hciConnectionThread,NULL);
36
	pthread_join(decisionMakingThread,NULL);
37

  
38
	exit(0);
39

  
40
}
41

  
42
// Decision-making thread routine
43
// Should just call a function that implements decision making module of the logic
44
void *decisionMakingThread_routine(void *dummy) {
45

  
46
	// TODO: Implemet decision making
47

  
48
	pthread_exit(0);
49

  
50
}
51

  
52
// HCI connection thread routine
53
// Start listening to some port
54
void *hciConnectionThread_routine(void *dummy) {
55

  
56
	int hciErrorCode = listenTo(1100);
57

  
58
	pthread_exit(0);
59

  
60
}
logic/trunk/src/init/config.xml
1
<init_config>
2
    <!--device containers-->
3
    <devices>
4
        <device id="Thermometer_01">
5
            <value>24</value>
6
        </device>
7
    </devices>
8
</init_config>
logic/trunk/src/init/devicelist.c
1
#include "devicelist.h"
2
#include <string.h>
3
#include <mxml.h>
4

  
5
device *hDevice; //device list
6

  
7
void setDeviceList()
8
{
9
    device *curr, *head;
10
    head = NULL;
11

  
12
    FILE *fp;
13
    mxml_node_t *tree, *node;
14

  
15
	fp = fopen("devicetree.xml", "r"); //TODO !hardcoded
16
	tree = mxmlLoadFile(NULL, fp, MXML_IGNORE_CALLBACK);
17
	node = tree;
18
	fclose(fp);
19

  
20
    /* //structure of XML tree
21
    ?xml
22
      |
23
    devicetree
24
      |
25
    dev1 - dev2 - ...
26
      |      |
27
      |      |
28
      |     ID - name - minvalue - maxvalue - action - param
29
    ID - name - minvalue - maxvalue - action - param
30
    /**/
31
    //getting to the correct level of the xml tree (descend 2 levels)
32
    node=node->child->child;
33
    printf("hDevice %d\n", hDevice);
34

  
35
    // fill the list of known devices
36
    // sorry for the ugly chunk of code, but I had to allocate memory
37
    // for each string separately in order to keep it scalable
38
    while(node!=NULL)
39
    {
40
        curr = (device *)malloc(sizeof(device));
41

  
42
        curr->id = (char *)malloc(sizeof(node->value.element.attrs->value));
43
        strcpy(curr->id, node->value.element.attrs->value);
44

  
45
        // getting data for individual device
46
        mxml_node_t *mxml_deviceNode;
47
        mxml_deviceNode=node->child;
48
        //TODO malloc()
49
        curr->name = (char *)malloc(sizeof(mxml_deviceNode->value.element.attrs->value));
50
        strcpy(curr->name, mxml_deviceNode->value.element.attrs->value);
51
            mxml_deviceNode= mxml_deviceNode->next;
52

  
53
        curr->minval= atoi(mxml_deviceNode->value.element.attrs->value);
54
            mxml_deviceNode= mxml_deviceNode->next;
55

  
56
        curr->maxval= atoi(mxml_deviceNode->value.element.attrs->value);
57
            mxml_deviceNode= mxml_deviceNode->next;
58

  
59
        curr->action = (char *)malloc(sizeof(mxml_deviceNode->value.element.attrs->value));
60
        strcpy(curr->action, mxml_deviceNode->value.element.attrs->value);
61
            mxml_deviceNode= mxml_deviceNode->next;
62

  
63
        curr->param = (char *)malloc(sizeof(mxml_deviceNode->value.element.attrs->value));
64
        strcpy(curr->param, mxml_deviceNode->value.element.attrs->value);
65
        // done
66
        // moving to the next XML node
67
        node=node->next;
68

  
69
        curr->nxt = head;
70
        head = curr;
71
    }
72
    //delete obsolete xml tree
73
    mxmlDelete(tree);
74
    mxmlDelete(node);
75
    /*
76
    // TODO delete - test
77
    hDevice=head;
78
    curr=head;
79
    printf("test device list\n");
80
    //*
81
    while(curr)
82
    {
83
        printf("name:\t %s\n", curr->name );
84
        printf("id:\t %s\n", curr->id );
85
        printf("minval:\t %d\n", curr->minval );
86
        printf("maxval:\t %d\n", curr->maxval );
87
        printf("action:\t %s\n", curr->action );
88
        printf("param:\t %s\n", curr->param );
89
        curr=curr->nxt;
90
    }
91
    /**/
92
}
93

  
94
/*
95
void updateDeviceList(device_d *deviceList)
96
{
97

  
98
}
99
/**/
logic/trunk/src/init/devicetree.xml
1
<?xml version="1.0"?>
2
<devicetree>
3
    <device id="thermometer_01">
4
        <name nam="Thermometer"></name>
5
        <minvalue minval="18"></minvalue>
6
        <maxvalue maxval="27"></maxvalue>
7
        <action act="testAction_1"></action>
8
        <param par="testParam_1"></param>
9
    </device>
10
    <device id="barometer_01">
11
        <name nam="Barometer"></name>
12
        <minvalue minval="18"></minvalue>
13
        <maxvalue maxval="27"></maxvalue>
14
        <action act="testAction_2"></action>
15
        <param par="testParam_2"></param>
16
    </device>
17
    <device id="hygrometer_01">
18
        <name nam="Hygrometer"></name>
19
        <minvalue minval="18"></minvalue>
20
        <maxvalue maxval="27"></maxvalue>
21
        <action act="testAction_3"></action>
22
        <param par="testParam_3"></param>
23
    </device>
24
    <device id="light_sensor_01">
25
        <name nam="Light sensor"></name>
26
        <minvalue minval="18"></minvalue>
27
        <maxvalue maxval="27"></maxvalue>
28
        <action act="testAction_4"></action>
29
        <param par="testParam_4"></param>
30
    </device>
31
    <device id="smart_meter_01">
32
        <name nam="Smart meter"></name>
33
        <minvalue minval="18"></minvalue>
34
        <maxvalue maxval="27"></maxvalue>
35
        <action act="testAction_5"></action>
36
        <param par="testParam_5"></param>
37
    </device>
38
</devicetree>
logic/trunk/src/init/devicelist.h
1
#ifndef DEVICELIST_H_INCLUDED
2
#define DEVICELIST_H_INCLUDED
3

  
4
//struct device_d ; /* Forward declaration */
5

  
6
typedef struct device_d
7
{
8
    char    *name;
9
    char    *id;
10
    int     minval;
11
    int     maxval;
12
    char    *action;
13
    char    *param;
14
    //TODO add circular buffer for each device
15
    struct  device_d *nxt;
16
}device;
17

  
18
void setNewDeviceList(); // ony called on startup
19
/*
20
void updateDeviceList(device_d *deviceList); // called on HMI change
21
char *getDeviceName();
22
char *getDeviceID();
23
?    requestDeviceUpdate(); //HMI naj nastavi parametre napravi
24
/**/
25
//check status?
26

  
27
#endif // DEVICELIST_H_INCLUDED
logic/trunk/eneraptor.layout
1
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
2
<CodeBlocks_layout_file>
3
	<ActiveTarget name="Debug" />
4
	<File name="devicelist.c" open="0" top="0" tabpos="2">
5
		<Cursor position="2830" topLine="75" />
6
	</File>
7
	<File name="initialisation.h" open="0" top="0" tabpos="8">
8
		<Cursor position="0" topLine="0" />
9
	</File>
10
	<File name="main.c" open="0" top="0" tabpos="1">
11
		<Cursor position="73" topLine="0" />
12
	</File>
13
</CodeBlocks_layout_file>
logic/trunk/eneraptor.depend
1
# depslib dependency file v1.0
2
1294839673 source:/home/janez/Documents/Dropbox/greenIT/eneraptor/main.c
3
	<stdio.h>
4
	<stdlib.h>
5

  
6
1294862485 source:/home/janez/Documents/Dropbox/greenIT/eneraptor/devicelist.c
7
	"devicelist.h"
8
	<string.h>
9
	<mxml.h>
10

  
11
1294858842 /home/janez/Documents/Dropbox/greenIT/eneraptor/devicelist.h
12

  
13
1294862456 source:/home/janez/Documents/Dropbox/greenIT/eneraptor/src/hci_comm/hci_comm_listener.c
14
	"hci_comm.h"
15
	<sys/types.h>
16
	<sys/socket.h>
17
	<netinet/in.h>
18
	<arpa/inet.h>
19
	<stdio.h>
20
	<stdlib.h>
21
	<string.h>
22
	<unistd.h>
23

  
24
1294862391 /home/janez/Documents/Dropbox/greenIT/eneraptor/src/hci_comm/hci_comm.h
25

  
26
1294862485 source:/home/janez/Documents/Dropbox/greenIT/eneraptor/src/init/devicelist.c
27
	"devicelist.h"
28
	<string.h>
29
	<mxml.h>
30

  
31
1294858842 /home/janez/Documents/Dropbox/greenIT/eneraptor/src/init/devicelist.h
32

  
33
1294863577 source:/home/janez/Documents/Dropbox/greenIT/eneraptor/src/startup/main.c
34
	"../hci_comm/hci_comm.h"
35
	<stdio.h>
36
	<pthread.h>
37

  
logic/trunk/eneraptor.cbp
1
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
2
<CodeBlocks_project_file>
3
	<FileVersion major="1" minor="6" />
4
	<Project>
5
		<Option title="eneraptor" />
6
		<Option pch_mode="2" />
7
		<Option compiler="gcc" />
8
		<Build>
9
			<Target title="Debug">
10
				<Option output="bin/Debug/eneraptor" prefix_auto="1" extension_auto="1" />
11
				<Option object_output="obj/Debug/" />
12
				<Option type="1" />
13
				<Option compiler="gcc" />
14
				<Compiler>
15
					<Add option="-g" />
16
				</Compiler>
17
				<Linker>
18
					<Add option="-lmxml" />
19
				</Linker>
20
			</Target>
21
			<Target title="Release">
22
				<Option output="bin/Release/eneraptor" prefix_auto="1" extension_auto="1" />
23
				<Option object_output="obj/Release/" />
24
				<Option type="1" />
25
				<Option compiler="gcc" />
26
				<Compiler>
27
					<Add option="-O2" />
28
				</Compiler>
29
				<Linker>
30
					<Add option="-s" />
31
				</Linker>
32
			</Target>
33
		</Build>
34
		<Compiler>
35
			<Add option="-Wall" />
36
		</Compiler>
37
		<Linker>
38
			<Add option="-lmxml" />
39
			<Add library="pthread" />
40
		</Linker>
41
		<Unit filename="devicelist.c">
42
			<Option compilerVar="CC" />
43
		</Unit>
44
		<Unit filename="devicelist.h" />
45
		<Unit filename="initialisation.h" />
46
		<Unit filename="main.c">
47
			<Option compilerVar="CC" />
48
		</Unit>
49
		<Unit filename="src/hci_comm/hci_comm.h" />
50
		<Unit filename="src/hci_comm/hci_comm_listener.c">
51
			<Option compilerVar="CC" />
52
		</Unit>
53
		<Extensions>
54
			<code_completion />
55
			<debugger />
56
		</Extensions>
57
	</Project>
58
</CodeBlocks_project_file>

Also available in: Unified diff