in-file config of the TemperatureControl, and simple adjustments to make
[clinton/Smoothieware.git] / src / libs / Config.cpp
CommitLineData
4cff3ded
AW
1/*
2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
6*/
7
8#include "mbed.h"
9#include <string>
10using std::string;
11#include "libs/Kernel.h"
12#include "Config.h"
4eb9c745
AW
13#include "libs/nuts_bolts.h"
14#include "libs/utils.h"
4cff3ded
AW
15
16Config::Config(){
17 config_file_found = false;
18}
19
cebe90b6
AW
20void Config::on_module_loaded(){
21 this->register_for_event(ON_CONSOLE_LINE_RECEIVED);
22}
23
24// When a new line is received, check if it is a command, and if it is, act upon it
25void Config::on_console_line_received( void* argument ){
26 string possible_command = *static_cast<string*>(argument);
27
28 // We don't compare to a string but to a checksum of that string, this saves some space in flash memory
29 unsigned short check_sum = get_checksum( possible_command.substr(0,possible_command.find_first_of(" \r\n")) ); // todo: put this method somewhere more convenient
da24d6ae 30 //this->kernel->serial->printf("checksum: %u \r\n", check_sum);
cebe90b6
AW
31
32 // Act depending on command
33 switch( check_sum ){
da24d6ae
AW
34 case config_get_checksum: this->config_get_command( get_arguments(possible_command)) ; break;
35 case config_set_checksum: this->config_set_command( get_arguments(possible_command)) ; break;
36 case config_load_checksum:this->config_load_command(get_arguments(possible_command)) ; break;
cebe90b6
AW
37 }
38}
39
26806df9
AW
40// Command to retreive the value of a specific configuration setting
41void Config::config_get_command( string parameter ){
b66fb830 42 this->kernel->serial->printf("%s\r\n", this->value( get_checksum( parameter ) )->value.c_str() );
26806df9
AW
43}
44
45// Command to set the value of a specific configuration setting
46void Config::config_set_command( string parameters ){
47 string setting = shift_parameter(parameters);
48 string value = shift_parameter(parameters);
49 this->set_string( get_checksum(setting), value );
50}
51
da24d6ae
AW
52// Command to reload configuration in all modules ( usefull if you changed one )
53void Config::config_load_command( string parameters ){
54 this->kernel->call_event(ON_CONFIG_RELOAD);
55}
56
26806df9
AW
57// Set a value from the configuration as a string
58// Because we don't like to waste space in Flash with lengthy config parameter names, we take a checksum instead so that the name does not have to be stored
59// See get_checksum
60void Config::set_string( uint16_t check_sum, string value ){
61 // Open the config file ( find it if we haven't already found it )
62 FILE *lp = fopen(this->get_config_file().c_str(), "r+");
63 string buffer;
64 int c;
65 // For each line
66 do {
67 c = fgetc (lp);
68 if (c == '\n'){
69 // We have a new line
70 if( buffer[0] == '#' ){ buffer.clear(); continue; } // Ignore comments
436a2cd1 71 if( buffer.length() < 3 ){ buffer.clear(); continue; } //Ignore empty lines
26806df9
AW
72 size_t begin_key = buffer.find_first_not_of(" ");
73 size_t begin_value = buffer.find_first_not_of(" ", buffer.find_first_of(" ", begin_key));
74 // If this line matches the checksum
75 if(get_checksum(buffer.substr(begin_key, buffer.find_first_of(" ", begin_key) - begin_key)) != check_sum){ buffer.clear(); continue; }
da24d6ae
AW
76 int free_space = int(int(buffer.find_first_of("\r\n#", begin_value+1))-begin_value);
77 if( int(value.length()) >= free_space ){ this->kernel->serial->printf("ERROR: Not enough room for value\r\n"); fclose(lp); return; }
26806df9 78 // Update value
da24d6ae 79 for( int i = value.length(); i < free_space; i++){ value += " "; }
26806df9
AW
80 fpos_t pos;
81 fgetpos( lp, &pos );
82 int start = pos - buffer.length() + begin_value - 1;
83 fseek(lp, start, SEEK_SET);
84 fputs(value.c_str(), lp);
26806df9
AW
85 fclose(lp);
86 return;
87 }else{
88 buffer += c;
89 }
90 } while (c != EOF);
91 fclose(lp);
92 this->kernel->serial->printf("ERROR: configuration key not found\r\n");
93}
cebe90b6 94
4cff3ded
AW
95// Get a value from the configuration as a string
96// Because we don't like to waste space in Flash with lengthy config parameter names, we take a checksum instead so that the name does not have to be stored
97// See get_checksum
b66fb830
AW
98ConfigValue* Config::value(uint16_t check_sum){
99 ConfigValue* result = new ConfigValue;
100 result->check_sum = check_sum;
7dd8133c
AW
101 if( this->has_config_file() == false ){
102 return result;
103 }
4cff3ded
AW
104 // Open the config file ( find it if we haven't already found it )
105 FILE *lp = fopen(this->get_config_file().c_str(), "r");
106 string buffer;
4eb9c745 107 int c;
4cff3ded
AW
108 // For each line
109 do {
110 c = fgetc (lp);
111 if (c == '\n'){
112 // We have a new line
113 if( buffer[0] == '#' ){ buffer.clear(); continue; } // Ignore comments
f5598f5b 114 if( buffer.length() < 3 ){ buffer.clear(); continue; } //Ignore empty lines
4cff3ded
AW
115 size_t begin_key = buffer.find_first_not_of(" ");
116 size_t begin_value = buffer.find_first_not_of(" ", buffer.find_first_of(" ", begin_key));
b66fb830
AW
117 string key = buffer.substr(begin_key, buffer.find_first_of(" ", begin_key) - begin_key);
118
4cff3ded 119 // If this line matches the checksum
b66fb830
AW
120 if(get_checksum(key) != check_sum){ buffer.clear(); continue; }
121 result->found = true;
122 result->key = key;
123 result->value = buffer.substr(begin_value, buffer.find_first_of("\r\n# ", begin_value+1)-begin_value);
b66fb830 124 break;
f5598f5b
AW
125 }else{
126 buffer += c;
4cff3ded
AW
127 }
128 } while (c != EOF);
129 fclose(lp);
b66fb830 130 return result;
4cff3ded
AW
131}
132
7dd8133c
AW
133bool Config::has_config_file(){
134 if( this->config_file_found ){ return true; }
4cff3ded
AW
135 this->try_config_file("/local/config");
136 this->try_config_file("/sd/config");
137 if( this->config_file_found ){
7dd8133c
AW
138 return true;
139 }else{
140 return false;
141 }
142
143}
144
145// Get the filename for the config file
146string Config::get_config_file(){
147 if( this->config_file_found ){ return this->config_file; }
148 if( this->has_config_file() ){
4cff3ded
AW
149 return this->config_file;
150 }else{
151 printf("ERROR: no config file found\r\n");
152 }
153}
154
cebe90b6
AW
155// Tool function for get_config_file
156inline void Config::try_config_file(string candidate){
4cff3ded
AW
157 FILE *lp = fopen(candidate.c_str(), "r");
158 if(lp){ this->config_file_found = true; this->config_file = candidate; }
159 fclose(lp);
160}
161
162
163