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