-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented basic SIM900 GSM firmware to test with.
- Loading branch information
1 parent
4b544b0
commit ba52555
Showing
4 changed files
with
390 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
#include "Commander.h" | ||
|
||
Commander::Commander(Stream *serial, char startToken, char endToken, char parameterDelimiter, char escapeChar) : | ||
serial(serial), | ||
startToken(startToken), | ||
endToken(endToken), | ||
parameterDelimiter(parameterDelimiter), | ||
escapeChar(escapeChar), | ||
lastChar('0'), | ||
parameterCount(0), | ||
command("") | ||
{ | ||
|
||
} | ||
|
||
boolean Commander::gotCommand() { | ||
boolean gotCommand = false; | ||
|
||
while (serial->available() > 0) { | ||
char character = serial->read(); | ||
|
||
if (character == startToken && lastChar != escapeChar) { | ||
buffer = ""; | ||
} else if (character == endToken && lastChar != escapeChar) { | ||
parseCommand(buffer); | ||
|
||
buffer = ""; | ||
gotCommand = true; | ||
|
||
lastChar = character; | ||
|
||
break; | ||
} else { | ||
if (character != escapeChar) { | ||
buffer += character; | ||
} | ||
|
||
lastChar = character; | ||
} | ||
} | ||
|
||
return gotCommand; | ||
} | ||
|
||
void Commander::parseCommand(String buffer) { | ||
parameterCount = 0; | ||
command = ""; | ||
|
||
int lastDelimiterPos = 0; | ||
int delimitersFound = 0; | ||
|
||
while (true) { | ||
// make sure we don't exceed the parameter limit | ||
if (parameterCount >= COMMANDER_MAX_PARAMETER_COUNT - 1) { | ||
break; | ||
} | ||
|
||
int delimiterPos = buffer.indexOf(parameterDelimiter, lastDelimiterPos + 1); | ||
|
||
if (delimiterPos == -1) { | ||
// there are no parameters so the whole command is a name | ||
if (delimitersFound == 0) { | ||
command = buffer; | ||
} | ||
|
||
break; | ||
} | ||
|
||
delimitersFound++; | ||
|
||
// first one is the name and parameters follow | ||
if (delimitersFound == 1) { | ||
command = buffer.substring(0, delimiterPos); | ||
} else { | ||
parameters[parameterCount++] = buffer.substring(lastDelimiterPos + 1, delimiterPos); | ||
} | ||
|
||
lastDelimiterPos = delimiterPos; | ||
} | ||
|
||
// extract last parameter | ||
if (delimitersFound > 0) { | ||
parameters[parameterCount++] = buffer.substring(lastDelimiterPos + 1, buffer.length()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#ifndef COMMANDER_H | ||
#define COMMANDER_H | ||
|
||
#include "Arduino.h" | ||
|
||
#define COMMANDER_MAX_PARAMETER_COUNT 10 | ||
|
||
class Commander { | ||
|
||
public: | ||
Commander(Stream *serial, char startToken = '<', char endToken = '>', char parameterDelimiter = ':', char escapeChar = '\\'); | ||
|
||
boolean gotCommand(); | ||
void parseCommand(String buffer); | ||
|
||
String command; | ||
String parameters[COMMANDER_MAX_PARAMETER_COUNT]; | ||
int parameterCount; | ||
|
||
private: | ||
Stream *serial; | ||
char startToken; | ||
char endToken; | ||
char parameterDelimiter; | ||
char escapeChar; | ||
char lastChar; | ||
String buffer; | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
#include "Commander.h" | ||
|
||
// application config | ||
const int GSM_BAUDRATE = 19200; | ||
const int COM_BAUDRATE = 115200; | ||
const unsigned long BTN_DEBOUNCE_PERIOD_MS = 300; | ||
|
||
// pin config | ||
const int GSM_PWRKEY_PIN = 9; | ||
|
||
// serials | ||
Serial_ *local = &Serial; | ||
HardwareSerial *remote = &Serial1; | ||
|
||
// runtime | ||
unsigned long lastUpdateTime = 0; | ||
unsigned long lastButtonPressTime = 0; | ||
boolean isGsmModulePoweredOn = false; | ||
|
||
Commander commander(local); | ||
|
||
void setup() { | ||
setupPinModes(); | ||
setupSerials(); | ||
} | ||
|
||
void loop() { | ||
unsigned long currentTime = millis(); | ||
unsigned long dt = currentTime - lastUpdateTime; | ||
updateSerials(currentTime, dt); | ||
updateCommander(currentTime, dt); | ||
|
||
lastUpdateTime = currentTime; | ||
} | ||
|
||
void setupPinModes() { | ||
pinMode(GSM_PWRKEY_PIN, OUTPUT); | ||
} | ||
|
||
void setupSerials() { | ||
local->begin(COM_BAUDRATE); | ||
remote->begin(GSM_BAUDRATE); | ||
} | ||
|
||
void updateSerials(unsigned long currentTime, unsigned long dt) { | ||
/*while (local->available() > 0) { | ||
char character = local->read(); | ||
remote->print(character); | ||
}*/ | ||
|
||
while (remote->available() > 0) { | ||
char character = remote->read(); | ||
|
||
local->print(character); | ||
} | ||
} | ||
|
||
void updateCommander(unsigned long currentTime, unsigned long dt) { | ||
while (commander.gotCommand()) { | ||
handleCommand(commander.command, commander.parameters, commander.parameterCount); | ||
} | ||
} | ||
|
||
void toggleGsmPower() { | ||
digitalWrite(GSM_PWRKEY_PIN, LOW); | ||
delay(1000); | ||
digitalWrite(GSM_PWRKEY_PIN, HIGH); | ||
delay(2000); | ||
digitalWrite(GSM_PWRKEY_PIN, LOW); | ||
delay(3000); | ||
|
||
local->println("done!"); | ||
} | ||
|
||
void sendTextMessage(String number, String message) { | ||
remote->print("AT+CMGF=1\r"); | ||
|
||
delay(100); | ||
remote->print("AT + CMGS = \""); | ||
remote->print(number); | ||
remote->println("\""); | ||
|
||
delay(100); | ||
remote->println(message); | ||
|
||
delay(100); | ||
remote->println((char)26);// the ASCII code of the ctrl+z is 26 | ||
|
||
delay(100); | ||
remote->println(); | ||
} | ||
|
||
void startCall(String number) { | ||
remote->print("ATD + "); | ||
remote->print(number); | ||
remote->println(";"); | ||
|
||
delay(100); | ||
remote->println(); | ||
} | ||
|
||
void endCall() { | ||
remote->println("ATH"); | ||
} | ||
|
||
void handleCommand(String command, String parameters[], int parameterCount) { | ||
if (command == "on" && parameterCount == 0) { | ||
handleOnCommand(); | ||
} else if (command == "off" && parameterCount == 0) { | ||
handleOffCommand(); | ||
} else if (command == "cmd" && parameterCount == 1) { | ||
handleCmdCommand(parameters); | ||
} else if (command == "sms" && parameterCount == 2) { | ||
handleSmsCommand(parameters); | ||
} else if (command == "call" && parameterCount == 1) { | ||
handleCallCommand(parameters); | ||
} else { | ||
local->print("Unhandled command '"); | ||
local->print(command); | ||
local->print("' with "); | ||
local->print(parameterCount); | ||
local->println(" parameters: "); | ||
|
||
for (int i = 0; i < parameterCount; i++) { | ||
local->print(" > "); | ||
local->print(i); | ||
local->print(": "); | ||
local->println(parameters[i]); | ||
} | ||
} | ||
} | ||
|
||
void handleOnCommand() { | ||
if (isGsmModulePoweredOn) { | ||
local->println("Module is already turned on, ignoring request"); | ||
|
||
return; | ||
} | ||
|
||
local->println("Turning GSM module on"); | ||
|
||
toggleGsmPower(); | ||
} | ||
|
||
void handleOffCommand() { | ||
if (!isGsmModulePoweredOn) { | ||
local->println("Module is already turned off, ignoring request"); | ||
|
||
return; | ||
} | ||
|
||
local->println("Turning GSM module off"); | ||
|
||
toggleGsmPower(); | ||
} | ||
|
||
void handleCmdCommand(String parameters[]) { | ||
String cmd = parameters[0]; | ||
|
||
local->print("Forwarding AT command '"); | ||
local->print(cmd); | ||
local->println("'"); | ||
|
||
remote->print(cmd); | ||
remote->print('\r'); | ||
} | ||
|
||
void handleSmsCommand(String parameters[]) { | ||
String number = parameters[0]; | ||
String message = parameters[1]; | ||
|
||
local->print("Sending SMS message '"); | ||
local->print(message); | ||
local->print("' to number '"); | ||
local->print(number); | ||
local->println("'"); | ||
|
||
sendTextMessage(number, message); | ||
} | ||
|
||
void handleCallCommand(String parameters[]) { | ||
String number = parameters[0]; | ||
|
||
local->print("Calling number '"); | ||
local->print(number); | ||
local->println("'"); | ||
|
||
startCall(number); | ||
delay(20000); | ||
endCall(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import path from 'path'; | ||
import bunyan from 'bunyan'; | ||
import { logger as config } from '../../config'; | ||
|
||
/* examples | ||
log('info "%d"', 123, { 'a': 1 }); | ||
log({ user: 'server' }, 'info "%d"', 123, { 'a': 1 }); | ||
log({ user: { firstName: 'Priit', lastName: 'Kallas' } }, 'user logged in'); | ||
log.warn('warning', 123, { 'a': 1 }); | ||
log.error('error', 123, { 'a': 1 }); | ||
log.error(new Error('Test error'), 'something went wrong...'); | ||
*/ | ||
|
||
// log levels | ||
const levels = [ | ||
'trace', // Logging from external libraries used by your app or very detailed application logging. | ||
'debug', // Anything else, i.e. too verbose to be included in "info" level. | ||
'info', // Detail on regular operation. | ||
'warn', // A note on something that should probably be looked at by an operator eventually. | ||
'error', // Fatal for a particular request, but the service/app continues servicing other requests. | ||
'fatal' // The service/app is going to stop or become unusable now. | ||
]; | ||
|
||
// default logger | ||
const defaultLog = bunyan.createLogger({ | ||
name: 'app', | ||
...config | ||
}); | ||
|
||
// default info logger | ||
const log = (...args) => { | ||
defaultLog.info(...args); | ||
}; | ||
|
||
// resolves full component filename to a relative component name | ||
function resolveComponentName(filename) { | ||
const componentFilename = path.resolve(filename); | ||
const currentFilename = path.resolve(__filename); | ||
const rootFilename = path.resolve(currentFilename, '../../../'); | ||
const relativeFilename = componentFilename.substr(rootFilename.length + 1); | ||
const dirname = path.dirname(relativeFilename); | ||
const extname = path.extname(relativeFilename); | ||
const basename = path.basename(relativeFilename, extname); | ||
const dirComponents = dirname.split(path.sep).filter( | ||
(dirComponent) => dirComponent.length > 0 && dirComponent !== '.' | ||
); | ||
|
||
return [...dirComponents, basename].join('/'); | ||
} | ||
|
||
// get a component logger | ||
log.get = (component, parameters = {}) => { | ||
const componentLog = defaultLog.child({ | ||
component: resolveComponentName(component), | ||
// streams: defaultLog.streams, | ||
...parameters | ||
}); | ||
|
||
/* | ||
const componentLog = bunyan.createLogger({ | ||
name: component, | ||
...defaultParameters, | ||
...parameters | ||
}); | ||
*/ | ||
|
||
const defaultFn = (...args) => { | ||
componentLog.info(...args); | ||
}; | ||
|
||
return Object.assign( | ||
defaultFn, | ||
levels.reduce((extenders, level) => { | ||
extenders[level] = (...args) => { | ||
componentLog[level](...args); | ||
}; | ||
|
||
return extenders; | ||
}, {}) | ||
); | ||
}; | ||
|
||
export default log; |