219e32f5115603fd0e3b47246d1901a6f9914f3f
[public/netxms.git] / src / agent / subagents / rpi / htsensor.cpp
1 /*
2 ** Raspberry Pi subagent
3 ** Copyright (C) 2013 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 **/
20
21 #include <nms_common.h>
22 #include <nms_agent.h>
23 #include <bcm2835.h>
24
25 #define GPIO_BASE 0x20200000
26 #define PIN 4
27
28 #define MAXTIMINGS 100
29
30 /**
31 * Sensor data
32 */
33 float g_sensorData[2];
34 time_t g_sensorUpdateTime;
35
36 /**
37 * Read data from sensor
38 */
39 static bool ReadSensor()
40 {
41 int data[MAXTIMINGS];
42 int counter = 0;
43 int laststate = HIGH;
44 int bits = 0;
45
46 // Set GPIO pin to output
47 bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP);
48
49 bcm2835_gpio_write(PIN, HIGH);
50 usleep(500000); // 500 ms
51 bcm2835_gpio_write(PIN, LOW);
52 usleep(20000);
53
54 bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT);
55
56 data[0] = data[1] = data[2] = data[3] = data[4] = 0;
57
58 // wait for pin to drop
59 counter = 0;
60 while (bcm2835_gpio_lev(PIN) == 1 && counter < 1000)
61 {
62 usleep(1);
63 counter++;
64 }
65
66 if (counter == 1000)
67 return false;
68
69 // read data
70 for(int i = 0; i< MAXTIMINGS; i++)
71 {
72 counter = 0;
73 while(bcm2835_gpio_lev(PIN) == laststate)
74 {
75 counter++;
76 if (counter == 1000)
77 break;
78 }
79 if (counter == 1000)
80 break;
81 laststate = bcm2835_gpio_lev(PIN);
82
83 if ((i > 3) && (i % 2 == 0))
84 {
85 // shove each bit into the storage bytes
86 data[bits / 8] <<= 1;
87 if (counter > 200)
88 {
89 data[bits / 8] |= 1;
90 }
91 bits++;
92 }
93 }
94
95 if ((bits >= 39) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)))
96 {
97 float h = (data[0] * 256 + data[1]) / 10.0;
98 float t = ((data[2] & 0x7F) * 256 + data[3]) / 10.0;
99 if (data[2] & 0x80)
100 t *= -1;
101
102 g_sensorData[0] = h;
103 g_sensorData[1] = t;
104 return true;
105 }
106
107 return 0;
108 }
109
110 /**
111 * Sensor polling thread
112 */
113 THREAD_RESULT THREAD_CALL SensorPollingThread(void *)
114 {
115 if (!bcm2835_init())
116 {
117 AgentWriteLog(NXLOG_ERROR, _T("RPI: call to bcm2835_init failed"));
118 return THREAD_OK;
119 }
120
121 AgentWriteDebugLog(1, _T("RPI: sensor polling thread started"));
122
123 while(1)
124 {
125 if (ReadSensor())
126 g_sensorUpdateTime = time(NULL);
127 ThreadSleepMs(500);
128 }
129
130 return THREAD_OK;
131 }