]> pilppa.org Git - lib1wire.git/blob - src/Factory.cc
Api cleanups for device querying
[lib1wire.git] / src / Factory.cc
1 /*
2  * Factory.cc
3  *
4  *  Created on: Dec 11, 2010
5  *      Author: lamikr
6  */
7
8 #include <string>
9 #include <sstream>
10 #include <iostream>
11
12 #include <string.h>
13
14 #include <plp/log.h>
15
16 #include "DeviceTypes.hh"
17 #include "Factory.hh"
18 #include "W1TemperatureSensor.hh"
19 #include "W1CounterDevice.hh"
20 #include "W1Util.hh"
21
22 using namespace w1;
23 using namespace plp;
24 using namespace std;
25
26 template <class NumberDataType>
27 bool string_to_number(NumberDataType& result,
28                  const std::string& string_param,
29                  std::ios_base& (*format)(std::ios_base&))
30 {
31         std::istringstream iss(string_param);
32         return !(iss >> format >> result).fail();
33 }
34
35 Factory::Factory() {
36         // TODO Auto-generated constructor stub
37 }
38
39 Factory::~Factory() {
40         // TODO Auto-generated destructor stub
41 }
42
43 int Factory::get_family_code_by_device_type(string device_type_param) {
44         int     ret_val = -1;
45
46         if (device_type_param.compare(DEVICE_TYPE_TEMPERATURESENSOR) == 0) {
47                 ret_val = 0x10;
48         }
49         else if (device_type_param.compare(DEVICE_TYPE_COUNTER_DEVICE) == 0) {
50                 ret_val = 0x1d;
51         }
52         return ret_val;
53 }
54
55 string Factory::get_device_type_by_family_code(int family_code_param) {
56         string  ret_val;
57
58         switch(family_code_param) {
59                 case    0x10:
60                 case    0x28:
61                         ret_val = DEVICE_TYPE_TEMPERATURESENSOR;
62                         break;
63                 case    0x1d:
64                         ret_val = DEVICE_TYPE_COUNTER_DEVICE;
65                         break;
66                 default:
67                         ret_val = DEVICE_TYPE_UNKNOWN;
68                         log_error("Unknown w1 device type: %d\n", family_code_param);
69                         break;
70         }
71         return ret_val;
72 }
73
74 Device *Factory::create_w1_device(int family_code_param,
75                         string device_id_param,
76                         dirent *direntry_param) {
77         Device          *ret_val;
78         DeviceConfig    *config;
79         string          type;
80
81         ret_val = NULL;
82         type    = get_device_type_by_family_code(family_code_param);
83         switch(family_code_param) {
84                 case    0x10:
85                 case    0x28:
86                         ret_val = new W1TemperatureSensor(type, device_id_param, direntry_param);
87                         break;
88                 case    0x1d:
89                         ret_val = new W1CounterDevice(type, device_id_param, direntry_param);
90                         break;
91                 case    0x81:
92                         // 0x81 is the 1-wire USB dongle... No need to create device for it.
93                         break;
94                 default:
95                         log_debug("Unsupported 1-wire-family code: %#x, device not created: %s\n", family_code_param, device_id_param.c_str());
96                         break;
97         }
98         if (ret_val != NULL) {
99                 // check that device config exist
100                 config  = get_device_config(device_id_param);
101                 if (config != NULL) {
102                         // if not, create default device config
103                         type    = config->get_cfg_value(DEVICE_CONFIG_VALUE_KEY__TYPE);
104                         if (type.empty() == true) {
105                                 type    = ret_val->get_device_type();
106                                 config->set_cfg_value(DEVICE_CONFIG_VALUE_KEY__TYPE, type);
107                                 config->set_cfg_value(DEVICE_CONFIG_VALUE_KEY__ID, ret_val->get_id());
108                         }
109                         delete(config);
110                 }
111         }
112         return ret_val;
113 }
114
115 Device *Factory::create_w1_device(string device_type_param,
116                         string device_id_param) {
117         int     family_code;
118         Device  *ret_val;
119
120         family_code     = get_family_code_by_device_type(device_type_param);
121         ret_val         = create_w1_device(family_code, device_id_param, NULL);
122         return ret_val;
123 }
124
125 Device *Factory::create_w1_device(dirent *direntry_param, int *err_code_param) {
126         string  folder_name;
127         string  tmp_str;
128         string  device_name;
129         int     pos;
130         int     family_code;
131         bool    suc_flg;
132         Device  *ret_val;
133
134         ret_val         = NULL;
135         *err_code_param = 0;
136         folder_name     = direntry_param->d_name;
137         pos             = folder_name.find("-");
138         if (pos > 0) {
139                 tmp_str = folder_name.substr(0, pos);
140                 // number in string is in hex format, convert to int
141                 suc_flg = string_to_number<int>(family_code, tmp_str, hex);
142                 // if family code = 0x81 (1-wire usb dongle), do not try to create the device
143                 if (family_code != 0x81) {
144                         if (suc_flg == true) {
145                                 log_debug("1-wire device family code: %#x\n", family_code);
146                                 device_name     = folder_name.substr(pos + 1, folder_name.length() - pos);
147                                 ret_val         = Factory::create_w1_device(family_code,
148                                                                 device_name,
149                                                                 direntry_param);
150                                 if ((ret_val == NULL) &&
151                                     (family_code != 0x81)) {
152                                         *err_code_param = 1;
153                                 }
154                         }
155                 }
156         }
157         return ret_val;
158 }
159
160 list<Device *> Factory::get_device_list() {
161         DIR                             *dir;
162         int                             err_flg;
163         struct dirent                   *direntry;
164         Device                          *device;
165         bool                            is_subdir;
166         list<DataReader *>              rdr_list;
167         list<Device *>                  ret_val;
168         list<Device *>::iterator        dev_iter;
169         list<DataReader *>::iterator    rdr_iter;
170         DataReader                      *reader;
171         string                          id1;
172         string                          id2;
173         string                          type;
174         string                          dev_type;
175         bool                            found;
176
177         // scan through the list of devices detected from the 1-wire network
178         dir     = opendir(W1_SCAN_ROOTDIR);
179         if (dir != NULL) {
180                 direntry        = readdir(dir);
181                 while(direntry != NULL) {
182                         is_subdir       = W1Util::is_subdirectory(W1_SCAN_ROOTDIR, direntry);
183                         if (is_subdir == true) {
184                                 err_flg = 0;
185                                 device  = create_w1_device(direntry, &err_flg);
186                                 if (device != NULL) {
187                                         ret_val.push_back(device);
188                                 }
189                                 else {
190                                         if (err_flg != 0) {
191                                                 log_info("Unsupported 1-wire device detected: %s\n", direntry->d_name);
192                                         }
193                                 }
194                         }
195                         direntry        = readdir(dir);
196                 }
197                 err_flg = closedir(dir);
198                 if (err_flg < 0) {
199                         log_error("Failed to close 1-wire device directory: %s\n", W1_SCAN_ROOTDIR);
200                 }
201         }
202         // scan through the list of devices which have saved data
203         rdr_list        = get_data_reader_list();
204         for (rdr_iter = rdr_list.begin(); rdr_iter != rdr_list.end(); rdr_iter++) {
205                 reader  = (DataReader *)*rdr_iter;
206                 id1     = reader->get_device_id();
207                 found   = false;
208                 for (dev_iter = ret_val.begin(); dev_iter != ret_val.end(); dev_iter++) {
209                         device  = (Device *)*dev_iter;
210                         id2     = device->get_id();
211                         if (id1.compare(id2) == 0) {
212                                 found   = true;
213                                 break;
214                         }
215                 }
216                 if (found == false) {
217                         // reader device is not in the list of active devices. create and add it to list as in-active one...
218                         type    = reader->get_device_type();
219                         device  = create_w1_device(type, id1);
220                         ret_val.push_back(device);
221                 }
222         }
223         return ret_val;
224 }
225
226 list<DataReader *> Factory::get_data_reader_list() {
227         DIR                     *dir;
228         string                  dr_name;
229         int                     err_flg;
230         struct dirent           *direntry;
231         DataReader              *reader;
232         bool                    is_subdir;
233         list<DataReader *>      ret_val;
234
235         dr_name = DeviceConfig::get_base_dir_name();
236         dir     = opendir(dr_name.c_str());
237         if (dir != NULL) {
238                 direntry        = readdir(dir);
239                 while(direntry != NULL) {
240                         if (strcmp(direntry->d_name, "cache") != 0) {
241                                 is_subdir       = W1Util::is_subdirectory(dr_name.c_str(), direntry);
242                                 if (is_subdir == true) {
243                                         reader  = new DataReader(direntry->d_name);
244                                         ret_val.push_back(reader);
245                                 }
246                         }
247                         direntry        = readdir(dir);
248                 }
249                 err_flg = closedir(dir);
250                 if (err_flg < 0) {
251                         log_error("Failed to close 1-wire device data directory: %s\n", dr_name.c_str());
252                 }
253         }
254         return ret_val;
255 }
256
257 DeviceConfig *Factory::get_device_config(string device_id) {
258         DeviceConfig    *ret_val;
259
260         ret_val = new DeviceConfig(device_id);
261         return ret_val;
262 }