diff --git a/config.example.yml b/config.example.yml index bc50de42c5ec418aeafab60b8e696aee2e90f440..b3cd54c824881359d24b563cc53049506beed2af 100644 --- a/config.example.yml +++ b/config.example.yml @@ -16,6 +16,7 @@ gpio_modules: - name: dev module: stdio + cleanup: no digital_inputs: - name: button @@ -32,6 +33,7 @@ digital_outputs: pin: 20 on_payload: "ON" off_payload: "OFF" + initial: low - name: test module: dev diff --git a/config.schema.yml b/config.schema.yml index 5ebb7f1fd8519c75e02faf07e19d23d6ba85ea0e..0fd7d4e983593b00df987dd9f099e898cb8fb6b7 100644 --- a/config.schema.yml +++ b/config.schema.yml @@ -67,6 +67,10 @@ gpio_modules: type: string required: yes empty: no + cleanup: + type: boolean + required: no + default: yes digital_inputs: type: list @@ -132,4 +136,10 @@ digital_outputs: inverted: type: boolean required: no - default: no \ No newline at end of file + default: no + initial: + type: string + required: no + allowed: + - high + - low diff --git a/pi_mqtt_gpio/__init__.py b/pi_mqtt_gpio/__init__.py index 329e6d8a80b662d6db51283325db2c2e52285604..1a5d53e17fcb93c6a3d2f61b52199d601b696103 100644 --- a/pi_mqtt_gpio/__init__.py +++ b/pi_mqtt_gpio/__init__.py @@ -1,4 +1,150 @@ -import sys -print("FATAL ERROR: The file at pi_mqtt_gpio/__init__.py should be replaced us" - "ing 'make schema' before packaging.") -sys.exit(1) +import yaml + +CONFIG_SCHEMA = yaml.load(""" +mqtt: + type: dict + required: yes + schema: + host: + type: string + empty: no + required: no + default: localhost + port: + type: integer + min: 1 + max: 65535 + required: no + default: 1883 + user: + type: string + required: no + default: "" + password: + type: string + required: no + default: "" + topic_prefix: + type: string + required: no + default: "" + coerce: rstrip_slash + protocol: + type: string + required: no + empty: no + coerce: tostring + default: "3.1.1" + allowed: + - "3.1" + - "3.1.1" + status_topic: + type: string + required: no + default: status + status_payload_running: + type: string + required: no + default: running + status_payload_stopped: + type: string + required: no + default: stopped + status_payload_dead: + type: string + required: no + default: dead + +gpio_modules: + type: list + required: yes + schema: + type: dict + allow_unknown: yes + schema: + name: + type: string + required: yes + empty: no + module: + type: string + required: yes + empty: no + cleanup: + type: boolean + required: no + default: yes + +digital_inputs: + type: list + required: no + default: [] + schema: + type: dict + schema: + name: + type: string + required: yes + empty: no + module: + type: string + required: yes + empty: no + pin: + type: integer + required: yes + min: 0 + on_payload: + type: string + required: yes + empty: no + off_payload: + type: string + required: yes + empty: no + pullup: + type: boolean + required: no + default: no + pulldown: + type: boolean + required: no + default: no + +digital_outputs: + type: list + required: no + default: [] + schema: + type: dict + schema: + name: + type: string + required: yes + module: + type: string + required: yes + pin: + type: integer + required: yes + min: 0 + on_payload: + type: string + required: no + empty: no + off_payload: + type: string + required: no + empty: no + inverted: + type: boolean + required: no + default: no + initial: + type: string + required: no + allowed: + - high + - low + +""") diff --git a/pi_mqtt_gpio/modules/__init__.py b/pi_mqtt_gpio/modules/__init__.py index 2e828939c981ba761a7461751164d73b60edda9f..7b7002c3103ef396fb5e7308c89bc80009077b3a 100644 --- a/pi_mqtt_gpio/modules/__init__.py +++ b/pi_mqtt_gpio/modules/__init__.py @@ -11,6 +11,11 @@ BASE_SCHEMA = { "module": { "required": True, "empty": False + }, + "cleanup": { + "required": False, + "type": "boolean", + "default": True } } diff --git a/pi_mqtt_gpio/modules/pcf8574.py b/pi_mqtt_gpio/modules/pcf8574.py index 1ca05f81da124ee036dd62611929242330a286f8..00ddb284164a447ead6c5644fc9ab48f3182a4ad 100644 --- a/pi_mqtt_gpio/modules/pcf8574.py +++ b/pi_mqtt_gpio/modules/pcf8574.py @@ -36,6 +36,12 @@ class GPIO(GenericGPIO): def setup_pin(self, pin, direction, pullup, pin_config): if direction == PinDirection.INPUT and pullup is not None: self.io.port[pin] = PULLUPS[pullup] + initial = pin_config.get("initial") + if initial is not None: + if initial == 'high': + self.set_pin(pin, True) + elif initial == 'low': + self.set_pin(pin, False) def set_pin(self, pin, value): self.io.port[pin] = value diff --git a/pi_mqtt_gpio/modules/raspberrypi.py b/pi_mqtt_gpio/modules/raspberrypi.py index 8f505c936d3ef8b47e5c1a9ec95ddeef8b1254f0..a6930956ce9bbe0e02876449e9beb8cb2dc2276c 100644 --- a/pi_mqtt_gpio/modules/raspberrypi.py +++ b/pi_mqtt_gpio/modules/raspberrypi.py @@ -36,7 +36,12 @@ class GPIO(GenericGPIO): else: pullup = PULLUPS[pullup] - self.io.setup(pin, direction, pull_up_down=pullup) + initial = { + None: -1, + "low": 0, + "high": 1 + }[pin_config.get("initial")] + self.io.setup(pin, direction, pull_up_down=pullup, initial=initial) def set_pin(self, pin, value): self.io.output(pin, value) diff --git a/pi_mqtt_gpio/modules/stdio.py b/pi_mqtt_gpio/modules/stdio.py index 5a55849a39959297bc1e824e6cfd55b01839dd9e..8aa68fadbf5fd5891fb8843cec10ca52ee5703c5 100644 --- a/pi_mqtt_gpio/modules/stdio.py +++ b/pi_mqtt_gpio/modules/stdio.py @@ -13,6 +13,12 @@ class GPIO(GenericGPIO): def setup_pin(self, pin, direction, pullup, pin_config): print("setup_pin(pin=%r, direction=%r, pullup=%r, pin_config=%r)" % ( pin, direction, pullup, pin_config)) + initial = pin_config.get("initial") + if initial is not None: + if initial == "high": + self.set_pin(pin, True) + elif initial == "low": + self.set_pin(pin, False) def set_pin(self, pin, value): print("set_pin(pin=%r, value=%r)" % (pin, value)) diff --git a/pi_mqtt_gpio/server.py b/pi_mqtt_gpio/server.py index 0caed5ff528bc568936a9c37a61d436cba94b09a..ab7818e9f648967de4c5bd57435b9d93cbfff002 100644 --- a/pi_mqtt_gpio/server.py +++ b/pi_mqtt_gpio/server.py @@ -23,6 +23,7 @@ LOG_LEVEL_MAP = { } RECONNECT_DELAY_SECS = 5 GPIO_MODULES = {} +GPIO_CONFIGS = {} LAST_STATES = {} SET_TOPIC = "set" SET_ON_MS_TOPIC = "set_on_ms" @@ -431,6 +432,7 @@ if __name__ == "__main__": client = init_mqtt(config["mqtt"], config["digital_outputs"]) for gpio_config in config["gpio_modules"]: + GPIO_CONFIGS[gpio_config["name"]] = gpio_config try: GPIO_MODULES[gpio_config["name"]] = configure_gpio_module( gpio_config) @@ -491,6 +493,9 @@ if __name__ == "__main__": # This should also quit the mqtt loop thread. client.disconnect() for name, gpio in GPIO_MODULES.items(): + if not GPIO_CONFIGS[name]["cleanup"]: + _LOG.info("Cleanup disabled for module %r.", name) + continue try: gpio.cleanup() except Exception: