├── README.md └── main.py /README.md: -------------------------------------------------------------------------------- 1 | ESP8266 IOT Button 2 | ================== 3 | 4 | ![Photo](http://i.imgur.com/osWEN4Z.jpg) 5 | 6 | This code is intended to be used with an ESP8266 flashed with MicroPython. 7 | See [here](http://imgur.com/a/e4KuA) for an album and more info on hardware. 8 | 9 | ![Schematic](http://i.imgur.com/mnZ3CU8.png) 10 | 11 | I used [esptool](https://github.com/espressif/esptool) to flash the MCU, and 12 | [ampy](https://github.com/adafruit/ampy) to perform the initial upload of 13 | `main.py`. After that, all other code uploads can be done using 14 | [webrepl](https://github.com/micropython/webrepl) 15 | 16 | To program, hold down S2 (the program button) while pressing S1 (the main 17 | button). This will put turn the device into an access point you can connect to. 18 | Look for an ssid that starts with "IOTBTN-". Then, use webrepl to connect to 19 | the device (just open webrepl.html in your browser, it's all client-side code). 20 | 21 | Use webrepl to upload a config.json file like so: 22 | 23 | ```json 24 | { 25 | "ssid": "your-wifi-ssid", 26 | "password": "your-wifi-password", 27 | "broker": "mqtt-broker-ip", 28 | "topic": "example/topic/name" 29 | } 30 | ``` 31 | 32 | Next time you press the button, the device will power up, publish the topic to 33 | the broker, and will then go into deep-sleep mode. The first press will connect 34 | using DHCP, and then save a static wifi config (this makes future connections a 35 | bit faster). So, the first press will take longer than subsequent presses. 36 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import utime as time 2 | import ujson as json 3 | import ubinascii as binascii 4 | import network 5 | import machine 6 | from machine import Pin 7 | from umqtt.simple import MQTTClient 8 | 9 | script_start = time.ticks_ms() 10 | CLIENT_ID = binascii.hexlify(machine.unique_id()).decode('utf-8') 11 | 12 | # load config 13 | with open('config.json', 'r') as config_file: 14 | config = json.load(config_file) 15 | 16 | # set up pins 17 | led = Pin(2, Pin.OUT, value=0) 18 | 19 | # To enable config mode (webrepl), connect GPIO0 to GND via 10K resistor 20 | config_mode_enabled = Pin(0, Pin.IN).value() == 0 21 | 22 | 23 | def run(): 24 | print('starting up...') 25 | 26 | # turn led on 27 | led.low() 28 | 29 | if config_mode_enabled: 30 | run_config_mode() 31 | else: 32 | run_action() 33 | 34 | # turn led off 35 | led.high() 36 | 37 | 38 | def finish(): 39 | print("total runtime: {}ms".format(time.ticks_ms() - script_start)) 40 | 41 | if not config_mode_enabled: 42 | print("sleeping...") 43 | machine.deepsleep() 44 | 45 | 46 | def connect_wifi(): 47 | wlan = network.WLAN(network.STA_IF) 48 | wlan.active(True) 49 | static = None 50 | 51 | try: 52 | with open('static.cfg', 'r') as static_cfg: 53 | print('found static config') 54 | static = static_cfg.read().strip().split('\n') 55 | if len(static) < 4: 56 | static = None 57 | except OSError: 58 | pass 59 | 60 | if static: 61 | print('using static config: ', static) 62 | wlan.ifconfig(static) 63 | 64 | if not wlan.isconnected(): 65 | print('connecting to network...') 66 | wlan.connect(config['ssid'], config['password']) 67 | while not wlan.isconnected(): 68 | pass 69 | 70 | if static is None: 71 | # save wifi config for faster reconnection 72 | ifconfig = '\n'.join(wlan.ifconfig()) 73 | with open('static.cfg', 'w') as static_cfg: 74 | print('Saving static config') 75 | static_cfg.write(ifconfig) 76 | 77 | 78 | def run_config_mode(): 79 | import webrepl 80 | ap = network.WLAN(network.AP_IF) 81 | ap_essid = config.get('ap_essid', 'IOTBTN-{}'.format(CLIENT_ID)) 82 | ap_password = config.get('ap_password', 'iotbutton') 83 | ap.config(essid=ap_essid, password=ap_password) 84 | webrepl.start() 85 | print('ESSID: {}\nPASS: {}'.format(ap_essid, ap_password)) 86 | 87 | 88 | def run_action(): 89 | connect_wifi() 90 | print('connecting to broker: {}'.format(config['broker'])) 91 | broker = config['broker'] 92 | topic = config.get('topic', 'button/{}'.format(CLIENT_ID.lower())) 93 | client = MQTTClient(CLIENT_ID, broker) 94 | client.connect() 95 | print('publishing topic: {} "pressed"'.format(topic)) 96 | client.publish(topic, 'pressed') 97 | client.disconnect() 98 | 99 | 100 | try: 101 | run() 102 | finally: 103 | finish() 104 | --------------------------------------------------------------------------------