load('api_config.js'); load('api_gpio.js'); load('api_mqtt.js'); load('api_net.js'); load('api_sys.js'); load('api_rpc.js'); load('api_timer.js'); load('api_file.js'); load('api_dlite.js'); // Helper C function get_led_gpio_pin() in src/main.c returns built-in LED GPIO // let button = Cfg.get('pins.button'); let topic = '/devices/' + Cfg.get('device.id') + '/events'; // let onBoardLed = ffi('int get_led_gpio_pin(void)')(); // print('LED GPIO:', onBoardLed, 'button GPIO:', button); let getInfo = function() { return JSON.stringify({ total_ram: Sys.total_ram(), free_ram: Sys.free_ram(), uptime: Sys.uptime() }); }; // Blink built-in LED every second /* GPIO.set_mode(onBoardLed, GPIO.MODE_OUTPUT); Timer.set(5000, true, function() { let value = GPIO.toggle(onBoardLed); print(value ? 'Tick' : 'Tock', 'uptime:', Sys.uptime(), getInfo()); }, null); */ // Publish to MQTT topic on a button press. Button is wired to GPIO pin 0 /* GPIO.set_button_handler(button, GPIO.PULL_UP, GPIO.INT_EDGE_NEG, 200, function() { let message = getInfo(); let ok = MQTT.pub(topic, message, 1); print('Published:', ok, topic, '->', message); }, null); */ // Monitor network connectivity. Net.setStatusEventHandler(function(ev, arg) { let evs = '???'; if (ev === Net.STATUS_DISCONNECTED) { evs = 'DISCONNECTED'; } else if (ev === Net.STATUS_CONNECTING) { evs = 'CONNECTING'; } else if (ev === Net.STATUS_CONNECTED) { evs = 'CONNECTED'; } else if (ev === Net.STATUS_GOT_IP) { evs = 'GOT_IP'; } print('==> NET:', ev, evs); }, null); let pin = Cfg.get('led.pin'); let configNumLeds = Cfg.get('led.count'); let colorFile = Cfg.get('led.colorFile'); let animationFile = Cfg.get('led.animationFile'); let lampsFile = Cfg.get('led.lampsFile'); let scheduleFile = Cfg.get('led.scheduleFile'); let dynamicMode = Cfg.get('led.mode'); let useDefaults = Cfg.get('led.useDefaults'); let tickDuration = Cfg.get('led.tickDuration'); let numberOfLeds = configNumLeds, numberOfLedDefs = 0; // from config files, count led definition entries /* Create test pattern */ function showLedTestPattern() { let i; let switchMod; for (i=0; i 5) print("WRONG -- should never reach this in switch statement!"); } NeoPixel_show(); } function allLedOn() { let i; for (i=0; i '9' && (color.color[i] < 'a' || color.color[i] > 'f'))) { print('ERROR: Color', color.name, 'has an invalid color definition.'); print(' Is:', color.color, ' but should #rgb where r/g/b is a 1-digit hex number in the range of 0..9a..f or #RGB where R/G/B is a 2-digit hex number'); return false; } } return true; } function hexToDec(digit) { if (digit >= 'a') return digit - 'a'; else if (digit >= 'A') return digit - 'A'; else return digit - '0'; } function getRedOfColorString(color) { if (color.length === 4) { return hexToDec(color.color[1]); } else { return hexToDec(color.color[1]) * 16 + hexToDec(color.color[2]); } } function getGreenOfColorString(color) { if (color.length === 4) { return hexToDec(color.color[2]); } else { return hexToDec(color.color[3]) * 16 + hexToDec(color.color[4]); } } function getBlueOfColorString(color) { if (color.length === 4) { return hexToDec(color.color[3]); } else { return hexToDec(color.color[5]) * 16 + hexToDec(color.color[6]); } } function loadColorDefs() { // Load Color definitions let json = File.read(colorFile); let colors = []; print('colorJson =', json); if (json === '') { print('ERROR: Color definition file does not exist!'); } else { colors = JSON.parse(json); } for (i=0; i configNumLeds) { print('WARNING: LED definition file contains more LEDs (', numberOfLedDefs, ') than configured in system-config (', configNumLeds, ')'); } json = null; // ledDef = null; // NO! Do not do this, as the strings are still referenced! } function loadAnimDefs() { // Load Animation Definitions let json = File.read(animationFile); let animation = []; print('animationFile =', json); if (json === '') { print('ERROR: Animation definition file does not exist!'); } else { animation = JSON.parse(json); } for (i=0; i 0 && args.level <= 100) { NeoPixel_setBrightness(args.level); return { result: 'ok' }; } else { return { error: 'Brightness level must be in the range 1..100' }; } } else { return { error: 'level is required having a value in the range 1..100' }; } }, "{level: %d}"); print(' led.getBrightness'); RPC.addHandler('led.getBrightness', function(args) { let brightness = NeoPixel_getBrightness(); return { result: 'ok', brightness: brightness }; }, null); print(' led.pause'); RPC.addHandler('led.pause', function(args) { LEDStateEngine_pause(); return { result: 'ok' }; }, null); print(' led.run'); RPC.addHandler('led.run', function(args) { LEDStateEngine_start(); return { result: 'ok' }; }, null); print(' led.getColors'); RPC.addHandler('led.getColors', function(args) { let colors = JSON.parse(File.read(colorFile)); return { result: 'ok', colors: colors }; }, null); print(' led.getLamps'); RPC.addHandler('led.getLamps', function(args) { let lamps = JSON.parse(File.read(lampsFile)); return { result: 'ok', lamps: lamps }; }, null); print(' led.getAnimations'); RPC.addHandler('led.getAnimations', function(args) { let anims = JSON.parse(File.read(animationFile)); return { result: 'ok', animations: anims }; }, null); function saveFile(filename, content) { let backupFilename = 'bak-' + filename; File.remove(backupFilename); File.rename(filename, backupFilename); File.write(JSON.stringify(content), filename); let backupFilename = null; } function recoverFile(filename) { let newerFilename = 'new-' + filename; let backupFilename = 'bak-' + filename; let bakFileContent = File.read(backupFilename); if (bakFileContent === '') { Log.error('recoverFile(' + filename + '): Backup file ' + backupFilename + ' does not exist or is empty'); return; } File.remove(newerFilename); File.rename(filename, newerFilename); File.rename(backupFilename, filename); } print(' led.putColors'); RPC.addHandler('led.putColors', function(args) { if (args !== undefined && args.colors !== undefined && args.colors[0] !== undefined && args.colors[0].name !== undefined && args.colors[0].color !== undefined) { saveFile(colorFile, args.colors); return { result: 'ok' }; } else { return { error: 'colors: {name, color} is required' }; } }, null); print(' led.putLamps'); RPC.addHandler('led.putLamps', function(args) { if (args !== undefined && args.lamps !== undefined) { saveFile(lampsFile, args.lamps); return { result: 'ok' }; } else { return { error: 'lamps: {level, room, id, onColor} is required' }; } }, null); print(' led.putAnimations'); RPC.addHandler('led.putAnimations', function(args) { if (args !== undefined && args.animations !== undefined) { saveFile(animationFile, args.animations); return { result: 'ok' }; } else { return { error: 'animations: {led, mode, ticks} is required' }; } }, null); print('***** End of init.js, sub tasks still running', getInfo());