From 6bdb9028af9a5256fbb47b942843e49aef7e3aa1 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Mon, 9 Apr 2018 22:42:45 +0800 Subject: Initial commit. --- CMakeLists.txt | 9 +++ COPYING | 28 ++++++++ ChangeLog | 3 + README.md | 37 +++++++++++ brightness_ctrl.cpp | 106 ++++++++++++++++++++++++++++++ brightness_ctrl.hpp | 35 ++++++++++ lightsd.conf | 34 ++++++++++ main.cpp | 163 ++++++++++++++++++++++++++++++++++++++++++++++ sensor_als.cpp | 11 ++++ sensor_als.hpp | 14 ++++ sensors.cpp | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++ sensors.hpp | 58 +++++++++++++++++ utils.cpp | 65 +++++++++++++++++++ utils.hpp | 12 ++++ 14 files changed, 756 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 README.md create mode 100644 brightness_ctrl.cpp create mode 100644 brightness_ctrl.hpp create mode 100644 lightsd.conf create mode 100644 main.cpp create mode 100644 sensor_als.cpp create mode 100644 sensor_als.hpp create mode 100644 sensors.cpp create mode 100644 sensors.hpp create mode 100644 utils.cpp create mode 100644 utils.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e8733c0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 2.6) +project(lightsd) +set(SOURCES brightness_ctrl.cpp sensor_als.cpp sensors.cpp utils.cpp main.cpp) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDART_REQUIRED ON) +find_package(Threads REQUIRED) +add_executable(${PROJECT_NAME} ${SOURCES}) +target_link_libraries(${PROJECT_NAME} stdc++fs) +target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT}) diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..eee20b4 --- /dev/null +++ b/COPYING @@ -0,0 +1,28 @@ +Copyright 2018 Chris Xiong + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..3d69246 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,3 @@ +2018-04-09 0.0.1 +First public version. +Almost feature complete. Only works for me though. diff --git a/README.md b/README.md new file mode 100644 index 0000000..facdd2d --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# lightsd + +`lightsd` is a small daemon to make your ~~(actually, my)~~ ambient +light sensor on your laptop useful in a Linux interjection +desktop without using a full desktop environment (or `systemd`). + +This service watches the readings from the ambient light sensor and +control the backlight of the screen and keyboard. It also creates a +fifo so that you can adjust relative brightness of the lcd. + +The project also demostrates how damn stupid a C++ program could look like. + +# Warning +WIP. Does not yet do any kind of input sanitation. May segmentation fault +at any time. The author uses Gentoo. _Very_ shitty code. + +AS A DAEMON, IT ONLY RUNS AS ROOT! + +# Building +Building _requires_ C++17. Just `mkdir build && cd build && cmake .. && make`. + +# Documentation +None. The code documentes itself. + +## fifo usage +- `u ` +Makes lcd x% brighter. +- `d ` +Makes lcd x% darker. +- `s ` +Set relative brightness of lcd. +- `r` +Reset relative brightness of lcd, equivalent to `s 0`. + +The fifo is owned by `root:video` and has permission `0620` so that +everyone in the video group could potentially mess with your brightness. +Surprise! diff --git a/brightness_ctrl.cpp b/brightness_ctrl.cpp new file mode 100644 index 0000000..3a57c0d --- /dev/null +++ b/brightness_ctrl.cpp @@ -0,0 +1,106 @@ +#include "brightness_ctrl.hpp" +#include "utils.hpp" +#include +#include +#define log10_n(x) ((x)<1?0:log10(x)) +void BrightnessControl::_brightness_slide(int p) +{ + p+=offset; + if(p>100)p=100; + if(p<0)p=0; + int pbr=maxbr*p/100; + printf("brightness adjust: %d->%d/%d\n",br,pbr,maxbr); + int d=1;if(pbr0&&br+round(d*dd)<=pbr||d<0&&br+round(d*dd)>=pbr) + { + br+=(int)round(d*dd);writeint(brpath.c_str(),br); + dd=dd*1.2;std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + br=pbr;writeint(brpath.c_str(),br); +} + +void BrightnessControl::init(float initv,SensorALS *s) +{ + cur=std::upper_bound(thresh.begin(),thresh.end(),(int)roundf(initv))-thresh.begin(); + als=s;set_offset(0,0); +} +void BrightnessControl::set_path(filesystem::path p) +{ + cpath=p; + brpath=cpath/"brightness"; + maxbrpath=cpath/"max_brightness"; + maxbr=readint(maxbrpath.c_str()); + br=readint(brpath.c_str()); +} +void BrightnessControl::set_thresh(std::vector _th){thresh=_th;} +void BrightnessControl::set_value(std::vector _v){value=_v;} +void BrightnessControl::set_delay(int _d){delay=_d;} +void BrightnessControl::set_trigrange(int _tr){tr=_tr;} + +void BrightnessControl::set_offset(int rel,int off) +{ + if(rel)offset+=rel*off;else offset=off; + if(offset>100)offset=100; + if(offset<-100)offset=-100; + brightness_slide(value[cur]); +} + +void BrightnessControl::on_sensor_report(float v) +{ + int lb=cur>0?thresh[cur-1]:0; + int ub=cur>1; + if(vub+log10_n(ub)*tr) + { + if(direction!=(v>ub)) + { + { + std::lock_guard lck(interrupt_m); + direction=(v>ub); + } + interrupt.notify_one(); + std::this_thread::yield(); + } + { + std::lock_guard lcd(threshnotify_m); + //nothing to do within this lock + } + threshnotify.notify_one(); + std::this_thread::yield(); + } +} +void BrightnessControl::brightness_slide(int p) +{ + std::thread brth(&BrightnessControl::_brightness_slide,std::ref(*this),p); + brth.detach(); +} +void BrightnessControl::worker() +{ + while(1) + { + std::unique_locklock_thresh(threshnotify_m); + threshnotify.wait(lock_thresh); + lock_thresh.unlock(); + std::cv_status intr; + do{ + std::unique_locklock_interrupt(interrupt_m); + intr=interrupt.wait_for(lock_interrupt,std::chrono::seconds(delay)); + lock_interrupt.unlock(); + }while(intr==std::cv_status::no_timeout); + //carry out brightness adjustment here + float val=als->get_value(); + int lb=cur>0?thresh[cur-1]:0; + int ub=cur>1; + while(val>ub) + { + ++cur;lb=thresh[cur-1]; + ub=cur>1; + } + while(val0?thresh[cur-1]:0; + ub=thresh[cur]; + } + printf("%f lx\n",val); + brightness_slide(value[cur]); + } +} diff --git a/brightness_ctrl.hpp b/brightness_ctrl.hpp new file mode 100644 index 0000000..4a94e0b --- /dev/null +++ b/brightness_ctrl.hpp @@ -0,0 +1,35 @@ +#ifndef BRIGHTNESS_CTRL_HPP +#define BRIGHTNESS_CTRL_HPP +#include +#include +#include +#include +#include +#include "sensor_als.hpp" +namespace filesystem=std::experimental::filesystem::v1; +class BrightnessControl +{ +private: + filesystem::path cpath,brpath,maxbrpath; + std::vector thresh,value; + int delay,direction,br,maxbr,tr,offset; + size_t cur; + SensorALS *als; + std::mutex interrupt_m,threshnotify_m; + std::condition_variable interrupt,threshnotify; + void _brightness_slide(int p); +public: + void init(float initv,SensorALS *s); + void set_path(filesystem::path p); + void set_thresh(std::vector _th); + void set_value(std::vector _v); + void set_delay(int _d); + void set_trigrange(int _tr); + + void set_offset(int rel,int off); + + void on_sensor_report(float v); + void brightness_slide(int p); + void worker(); +}; +#endif diff --git a/lightsd.conf b/lightsd.conf new file mode 100644 index 0000000..ca47344 --- /dev/null +++ b/lightsd.conf @@ -0,0 +1,34 @@ +#example configuration for lightsd + +#path to backlight control in sysfs +#expected files are max_brightness and brightness +lcd_backlight_control=/sys/class/backlight/intel_backlight + +#path to keyboard backlight control in sysfs +#expected files are max_brightness and brightness +kbd_backlight_control=/sys/bus/platform/devices/thinkpad_acpi/leds/tpacpi::kbd_backlight + +#list of (*increasing* _integer_) threshold values from the ambient light sensor, separated by commas +lcd_backlight_thresholds=10,20,50,100,500,2000,10000 + +#list of (_integer_) brightnesses (percentage) corresponding to the thresholds +lcd_backlight_values=3,5,10,15,30,60,80,100 + +#seconds before a brightness change really takes place +#(any als reading change crossing a threshold resets the timer) +lcd_backlight_control_delay=3 + +#don't trigger a brightness change until sensor reading away from +#the threshold exceeds this value +#this is a relative value, multiplied by logarithm of the compared +#threshold before using +lcd_backlight_trigger_range=2 + +#same as their lcd conterpart +kbd_backlight_thresholds=100 +kbd_backlight_values=50,0 +kbd_backlight_control_delay=5 +kbd_backlight_trigger_range=2 + +#where to create the fifo for remote control +command_fifo_path=/tmp/lightsd.cmd.fifo diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..df3af34 --- /dev/null +++ b/main.cpp @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.hpp" +#include "sensor_als.hpp" +#include "brightness_ctrl.hpp" +SensorALS als; +int als_id; + +filesystem::path fifo_path; +BrightnessControl lcd,kbd; +FILE *fifo_f; + +void als_callback(SensorBase* _s) +{ + SensorALS* s=(SensorALS*)_s; + float val=s->get_value(); + lcd.on_sensor_report(val); + kbd.on_sensor_report(val); +} +void load_config() +{ + fifo_path="/tmp/lightsd.cmd.fifo"; + FILE* cfgf; + cfgf=fopen("/etc/lightsd.conf","r"); + if(!cfgf) + cfgf=fopen("lightsd.conf","r"); + if(!cfgf){LOG('W',"Configuration file not found.",0);return;} + char* buf=new char[1024]; + while(!feof(cfgf)) + { + fgets(buf,1024,cfgf); + if(buf[0]=='#')continue; + std::string sb=trim(buf); + std::vector sv; + split(sb,'=',sv); + if(sv.size()!=2)continue; + if(sv[0]=="lcd_backlight_control")lcd.set_path(sv[1]); + if(sv[0]=="kbd_backlight_control")kbd.set_path(sv[1]); + if(sv[0]=="lcd_backlight_thresholds") + { + std::vector vals; + split(sv[1],',',vals); + std::vector t; + for(auto&i:vals)t.push_back(atoi(i.c_str())); + lcd.set_thresh(t); + } + if(sv[0]=="lcd_backlight_values") + { + std::vector vals; + split(sv[1],',',vals); + std::vector t; + for(auto&i:vals)t.push_back(atoi(i.c_str())); + lcd.set_value(t); + } + if(sv[0]=="lcd_backlight_control_delay")lcd.set_delay(atoi(sv[1].c_str())); + if(sv[0]=="lcd_backlight_trigger_range")lcd.set_trigrange(atoi(sv[1].c_str())); + if(sv[0]=="kbd_backlight_thresholds") + { + std::vector vals; + split(sv[1],',',vals); + std::vector t; + for(auto&i:vals)t.push_back(atoi(i.c_str())); + kbd.set_thresh(t); + } + if(sv[0]=="kbd_backlight_values") + { + std::vector vals; + split(sv[1],',',vals); + std::vector t; + for(auto&i:vals)t.push_back(atoi(i.c_str())); + kbd.set_value(t); + } + if(sv[0]=="kbd_backlight_control_delay")kbd.set_delay(atoi(sv[1].c_str())); + if(sv[0]=="kbd_backlight_trigger_range")kbd.set_trigrange(atoi(sv[1].c_str())); + if(sv[0]=="command_fifo_path")fifo_path=sv[1]; + } + delete[] buf; +} +int get_gid(std::string group) +{ + FILE* grpf=fopen("/etc/group","r"); + char* buf=new char[1024]; + while(!feof(grpf)) + { + fgets(buf,1024,grpf); + std::vector sv; + split(buf,':',sv); + if(sv[0]==group) + { + fclose(grpf); + delete[] buf; + return atoi(sv[2].c_str()); + } + } + fclose(grpf); + delete[] buf; + return -1; +} +void setup_fifo() +{ + if(!fifo_path.string().length())return; + unlink(fifo_path.c_str()); + mkfifo(fifo_path.c_str(),0620); + chown(fifo_path.c_str(),0,get_gid("video")); + chmod(fifo_path.c_str(),0620); +} +void command_thread() +{ + fifo_f=fopen(fifo_path.c_str(),"r"); + char cmdbuf[256]; + while(1) + { + fgets(cmdbuf,256,fifo_f); + printf("got command: "); + puts(trim(cmdbuf).c_str()); + std::vector cav; + split(trim(cmdbuf),' ',cav); + if(cav.size()>=1) + { + if(cav[0]=="u")if(cav.size()>1)lcd.set_offset(1,atoi(cav[1].c_str())); + if(cav[0]=="d")if(cav.size()>1)lcd.set_offset(-1,atoi(cav[1].c_str())); + if(cav[0]=="s")if(cav.size()>1)lcd.set_offset(0,atoi(cav[1].c_str())); + if(cav[0]=="r")lcd.set_offset(0,0); + } + fclose(fifo_f); + fifo_f=fopen(fifo_path.c_str(),"r"); + } +} +void sigterm_handler(int) +{ + exit(0); +} +int main() +{ + signal(SIGTERM,sigterm_handler); + als_id=SensorBase::detect_sensor("als"); + if(!~als_id)return puts("No ALS found!"),1; + als.init(als_id,"in_intensity"); + als.set_reader_callback(als_callback); + float init_val=als.get_value(); + printf("initial value: %f lx\n",init_val); + load_config(); + setup_fifo(); + lcd.init(init_val,&als); + kbd.init(init_val,&als); + std::thread lcd_thread(&BrightnessControl::worker,std::ref(lcd)); + std::thread kbd_thread(&BrightnessControl::worker,std::ref(kbd)); + std::thread cmd_thread(command_thread); + als.worker(); + return 0; +} diff --git a/sensor_als.cpp b/sensor_als.cpp new file mode 100644 index 0000000..399f2a1 --- /dev/null +++ b/sensor_als.cpp @@ -0,0 +1,11 @@ +#include "sensor_als.hpp" +void SensorALS::enable_scan_elements() +{ + enable_scan_element("both"); +} +void SensorALS::update_values() +{ + value=std::any_cast(dict["in_intensity_both_value"])* + std::any_cast(dict["in_intensity_scale"]); +} +float SensorALS::get_value(){return value;} diff --git a/sensor_als.hpp b/sensor_als.hpp new file mode 100644 index 0000000..0548545 --- /dev/null +++ b/sensor_als.hpp @@ -0,0 +1,14 @@ +#ifndef SENSOR_ALS_HPP +#define SENSOR_ALS_HPP +#include "sensors.hpp" +class SensorALS:public SensorBase +{ + private: + float value; + protected: + void enable_scan_elements(); + public: + void update_values(); + float get_value(); +}; +#endif diff --git a/sensors.cpp b/sensors.cpp new file mode 100644 index 0000000..8817528 --- /dev/null +++ b/sensors.cpp @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include +#include "utils.hpp" +#include "sensors.hpp" +void SensorBase::parse_type_string(std::string type,scan_t* ti) +{ + char endian[4],sign; + if(type.find('X')!=type.npos) + sscanf(type.c_str(),"%2s:%c%hhu/%hhuX%hhu>>%hhu", + endian,&sign,&ti->bits,&ti->storagebits,&ti->repeat,&ti->shift + ); + else + { + ti->repeat=0; + sscanf(type.c_str(),"%2s:%c%hhu/%hhu>>%hhu", + endian,&sign,&ti->bits,&ti->storagebits,&ti->shift + ); + } + ti->is_le=std::string(endian)=="le"; + ti->is_signed=sign=='s'; +} +void SensorBase::readbuffer() +{ + char* buf=new char[readsize]; + ssize_t sz=read(devfd,buf,readsize); + if(sz==readsize) + { + char *p=buf; + for(int i=0;p-buf(enabled_scan_elem[i]); + std::string es=std::get(enabled_scan_elem[i])+"_value"; + if(ti.is_le) + switch(ti.storagebits) + { + case 8: + if(ti.is_signed) + {int8_t t;memcpy(&t,p,1);t>>=ti.shift;dict[es]=t;} + else + {uint8_t t;memcpy(&t,p,1);t>>=ti.shift;dict[es]=t;} + ++p; + break; + case 16: + if(ti.is_signed) + {int16_t t;memcpy(&t,p,2);t>>=ti.shift;dict[es]=t;} + else + {uint16_t t;memcpy(&t,p,2);t>>=ti.shift;dict[es]=t;} + p+=2; + break; + case 32: + if(ti.is_signed) + {int32_t t;memcpy(&t,p,4);t>>=ti.shift;dict[es]=t;} + else + {uint32_t t;memcpy(&t,p,4);t>>=ti.shift;dict[es]=t;} + p+=4; + break; + case 64: + if(ti.is_signed) + {int64_t t;memcpy(&t,p,8);t>>=ti.shift;dict[es]=t;} + else + {uint64_t t;memcpy(&t,p,8);t>>=ti.shift;dict[es]=t;} + p+=8; + break; + } + } + } + delete[] buf; +} +void SensorBase::enable_buffer() +{ + using filesystem::path; + + path buffer_enable_path=sysfspath/"buffer"/"enable"; + writeint(buffer_enable_path.c_str(),1); +} +void SensorBase::enable_scan_element(std::string elem) +{ + using filesystem::path; + std::string elem_base=sensor_basename+(elem.length()?"_"+elem:""); + + path elem_type_path=sysfspath/"scan_elements"/(elem_base+"_type"); + std::string ts;dict[elem_base+"_type"]=ts=readstr(elem_type_path.c_str()); + scan_t st;parse_type_string(ts,&st); + readsize+=st.storagebits/8;//assume this shit is aligned to byte + + path elem_en_path=sysfspath/"scan_elements"/(elem_base+"_en"); + writeint(elem_en_path.c_str(),1); + + path elem_idx_path=sysfspath/"scan_elements"/(elem_base+"_index"); + int idx;dict[elem_base+"_index"]=idx=readint(elem_idx_path.c_str()); + + path raw_val_path=sysfspath/(elem_base+"_raw");//initial value + dict[elem_base+"_value"]=readint(raw_val_path.c_str()); + + enabled_scan_elem.insert( + std::upper_bound(enabled_scan_elem.begin(),enabled_scan_elem.end(), + std::make_tuple(idx,elem_base,st), + [](const auto&a,const auto&b)->bool{return std::get<0>(a)(b);} + ),std::make_tuple(idx,elem_base,st) + ); +} +void SensorBase::init(int id,std::string _sensor_basename) +{ + sysfspath=IIODEV_SYSFS_PATH_BASE+std::to_string(id); + devbufpath=DEV_PATH+std::to_string(id); + sensor_basename=_sensor_basename; + + using filesystem::path; + path name_path=sysfspath/"name"; + type=readstr(name_path.c_str()); + path scale_path=sysfspath/(sensor_basename+"_scale"); + dict[sensor_basename+"_scale"]=readfloat(scale_path.c_str()); + path offset_path=sysfspath/(sensor_basename+"_offset"); + dict[sensor_basename+"_offset"]=readfloat(offset_path.c_str()); + + readsize=0; + enabled_scan_elem.clear(); + enable_scan_elements(); + update_values(); + enable_buffer(); + devfd=open(devbufpath.c_str(),O_RDONLY); + if(!~devfd)LOG('E',"failed to open the iio buffer device: %s",devbufpath.c_str()); +} +void SensorBase::deinit() +{ + if(~devfd)close(devfd); + devfd=-1; +} +void SensorBase::reset() +{ + deinit(); + using filesystem::path; + + path buffer_enable_path=sysfspath/"buffer"/"enable"; + writeint(buffer_enable_path.c_str(),0); + for(auto& ent:filesystem::directory_iterator(sysfspath/"scan_elements")) + if(ent.path().string().substr(ent.path().string().length()-3)=="_en") + writeint(ent.path().c_str(),0); +} +void SensorBase::worker() +{ + for(workerquit=0;!workerquit;) + { + readbuffer();update_values(); + if(readercb!=nullptr)readercb(this); + } +} +void SensorBase::quit_worker() +{workerquit=1;} +void SensorBase::set_reader_callback(std::function cb) +{readercb=cb;} +std::string SensorBase::get_type(int id) +{ + using filesystem::path; + path sysfspath=path(IIODEV_SYSFS_PATH_BASE+std::to_string(id)); + + path name_path=sysfspath/"name"; + return readstr(name_path.c_str()); +} +int SensorBase::detect_sensor(std::string type) +{ + using filesystem::path; + path sysfsbasepath=path(IIODEV_SYSFS_PATH_BASE).remove_filename(); + for(auto& ent:filesystem::directory_iterator(sysfsbasepath)) + { + path name_path=ent.path()/"name"; + if(trim(readstr(name_path.c_str()))==type) + { + std::string es=ent.path().filename().string(); + size_t i; + for(i=0;i'9');++i); + if(i +#include +#include +#include +#include +#include +#include +#include + +#define IIODEV_SYSFS_PATH_BASE "/sys/bus/iio/devices/iio:device" +#define DEV_PATH "/dev/iio:device" + +namespace filesystem=std::experimental::filesystem::v1; + +struct scan_t +{ + bool is_le; + bool is_signed; + uint8_t bits,storagebits; + uint8_t shift,repeat; +}; + +class SensorBase +{ + private: + int devfd; + int workerquit; + int readsize; + std::function readercb; + std::vector> enabled_scan_elem; + + void enable_buffer(); + void parse_type_string(std::string type,scan_t* ti); + void readbuffer(); + protected: + std::string type,sensor_basename; + filesystem::path devbufpath; + filesystem::path sysfspath; + std::unordered_map dict; + + void enable_scan_element(std::string elem); + + virtual void enable_scan_elements()=0; + virtual void update_values()=0; + public: + virtual ~SensorBase(){} + void init(int id,std::string _sensor_basename); + void deinit(); + void reset(); + void worker(); + void quit_worker(); + void set_reader_callback(std::function cb); + static std::string get_type(int id); + static int detect_sensor(std::string type); +}; +#endif diff --git a/utils.cpp b/utils.cpp new file mode 100644 index 0000000..8dc5f5a --- /dev/null +++ b/utils.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include "utils.hpp" +int readint(const char* path) +{ + FILE* f=fopen(path,"r"); + if(!f)return LOG('W',"failed to open %s for reading: %d",path,errno),0; + char buf[16]; + fgets(buf,16,f); + buf[15]=0; + fclose(f); + return atoi(buf); +} +float readfloat(const char* path) +{ + FILE* f=fopen(path,"r"); + if(!f)return LOG('W',"failed to open %s for reading: %d",path,errno),0; + char buf[16]; + fgets(buf,16,f); + buf[15]=0; + fclose(f); + return atof(buf); +} +std::string readstr(const char* path) +{ + FILE* f=fopen(path,"r"); + if(!f)return LOG('W',"failed to open %s for reading: %d",path,errno),""; + char buf[256]; + fgets(buf,256,f); + buf[255]=0; + fclose(f); + return std::string(buf); +} +void writeint(const char* path,int v) +{ + FILE* f=fopen(path,"w"); + if(!f){LOG('W',"failed to open %s for writing",path);return;} + fprintf(f,"%d",v); + fclose(f); +} +std::string trim(std::string s) +{ + size_t st=0; + for(;st& v) +{ + v.clear(); + for(size_t anch=0;;) + { + std::string sec; + if(s.find(c,anch)==std::string::npos) + sec=s.substr(anch); + else sec=s.substr(anch,s.find(c,anch)-anch); + v.push_back(sec); + if(s.find(c,anch)==std::string::npos)break; + anch=s.find(c,anch)+1; + } +} diff --git a/utils.hpp b/utils.hpp new file mode 100644 index 0000000..055201d --- /dev/null +++ b/utils.hpp @@ -0,0 +1,12 @@ +#ifndef UTILS_HPP +#define UTILS_HPP +#include +#include +#define LOG(type,format,...) fprintf(stderr,"%c: " format "\n",type,__VA_ARGS__) +extern int readint(const char* path); +extern float readfloat(const char* path); +extern std::string readstr(const char* path); +extern void writeint(const char* path,int v); +extern std::string trim(std::string s); +extern void split(std::string s,char c,std::vector& v); +#endif -- cgit v1.2.3