AM2302(DHT22) sensors support.
[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 * Collector Thread data
32 */
33 static bool volatile m_stopCollectorThread = false;
34 static THREAD m_collector = INVALID_THREAD_HANDLE;
35
36 /**
37 * Sensor data
38 */
39 float g_sensorData[2];
40 time_t g_sensorUpdateTime;
41
42 /**
43 * Read data from sensor
44 */
45 static bool ReadSensor()
46 {
47 int data[MAXTIMINGS];
48 int counter = 0;
49 int laststate = HIGH;
50 int bits = 0;
51
52 // Set GPIO pin to output
53 bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP);
54
55 bcm2835_gpio_write(PIN, HIGH);
56 //usleep(500000);
57 ThreadSleepMs(500);
58 bcm2835_gpio_write(PIN, LOW);
59 ThreadSleepMs(20);
60 //usleep(20000);
61
62 bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT);
63
64 data[0] = data[1] = data[2] = data[3] = data[4] = 0;
65
66 // wait for pin to drop
67 counter = 0;
68 while (bcm2835_gpio_lev(PIN) == 1 && counter < 1000)
69 {
70 struct timespec ts;
71 ts.tv_sec = 0;
72 ts.tv_nsec = 1000;
73 nanosleep(&ts, NULL);
74 //usleep(1);
75 //ThreadSleepMs(1);
76 counter++;
77 }
78
79 if (counter == 1000)
80 {
81 return false;
82 }
83
84 // read data
85 for(int i = 0; i< MAXTIMINGS; i++)
86 {
87 counter = 0;
88 while(bcm2835_gpio_lev(PIN) == laststate)
89 {
90 counter++;
91 if (counter == 1000)
92 break;
93 }
94 if (counter == 1000)
95 break;
96 laststate = bcm2835_gpio_lev(PIN);
97
98 if ((i > 3) && (i % 2 == 0))
99 {
100 // shove each bit into the storage bytes
101 data[bits / 8] <<= 1;
102 if (counter > 200)
103 {
104 data[bits / 8] |= 1;
105 }
106 bits++;
107 }
108 }
109
110 if ((bits >= 39) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)))
111 {
112 float h = (data[0] * 256 + data[1]) / 10.0;
113 float t = ((data[2] & 0x7F) * 256 + data[3]) / 10.0;
114 if (data[2] & 0x80)
115 t *= -1;
116
117 g_sensorData[0] = h;
118 g_sensorData[1] = t;
119
120 printf("t=%f, h=%f\n", t, h);
121 return true;
122 }
123
124 return 0;
125 }
126
127 /**
128 * Sensor polling thread
129 */
130 THREAD_RESULT THREAD_CALL SensorPollingThread(void *)
131 {
132 AgentWriteDebugLog(1, _T("RPI: sensor polling thread started"));
133
134 while(!m_stopCollectorThread)
135 {
136 if (ReadSensor())
137 {
138 g_sensorUpdateTime = time(NULL);
139 }
140 ThreadSleepMs(1500);
141 }
142
143 return THREAD_OK;
144 }
145
146 BOOL StartSensorCollector()
147 {
148 if (!bcm2835_init())
149 {
150 AgentWriteLog(NXLOG_ERROR, _T("RPI: call to bcm2835_init failed"));
151 return FALSE;
152 }
153 m_collector = ThreadCreateEx(SensorPollingThread, 0, NULL);
154 return TRUE;
155 }
156
157 void StopSensorCollector()
158 {
159 m_stopCollectorThread = true;
160 if (m_collector != INVALID_THREAD_HANDLE)
161 {
162 ThreadJoin(m_collector);
163 bcm2835_close();
164 }
165 }