├── .clang-format ├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .github ├── version.py └── workflows │ ├── Dockerfile-esp32-build │ ├── Dockerfile-mos │ ├── build.yaml │ ├── check-format.yaml │ ├── howto.build │ └── stale.yml ├── .gitignore ├── AUTHORS.md ├── LICENSE ├── Makefile ├── README.md ├── docs └── SDNT1608-0.1-10.png ├── fs └── favicon.ico.gz ├── fs_src ├── index.html ├── logo.svg ├── qrcode.js ├── script.js ├── sha256.js └── style.css ├── libreset ├── include │ └── shelly_reset.hpp ├── mos.yml └── src │ └── shelly_reset.cpp ├── mos.yml ├── src ├── ADE7953 │ ├── shelly_pm_ade7953.cpp │ └── shelly_pm_ade7953.hpp ├── BL0937 │ ├── shelly_pm_bl0937.cpp │ └── shelly_pm_bl0937.hpp ├── BL0942 │ ├── shelly_pm_bl0942.cpp │ └── shelly_pm_bl0942.hpp ├── DHT │ ├── shelly_dht_sensor.cpp │ └── shelly_dht_sensor.hpp ├── DS18XXX │ ├── shelly_temp_sensor_ow.cpp │ └── shelly_temp_sensor_ow.hpp ├── Shelly1 │ └── shelly_init.cpp ├── Shelly1L │ └── shelly_init.cpp ├── Shelly1PM │ └── shelly_init.cpp ├── Shelly2 │ └── shelly_init.cpp ├── Shelly25 │ ├── shelly_init_components.cpp │ └── shelly_init_peripherals.cpp ├── ShellyColorBulb │ └── shelly_init.cpp ├── ShellyDuo │ └── shelly_init.cpp ├── ShellyI3 │ └── shelly_init.cpp ├── ShellyMini1Gen3 │ └── shelly_init.cpp ├── ShellyMini1PMGen3 │ └── shelly_init.cpp ├── ShellyPlug │ └── shelly_init.cpp ├── ShellyPlugS │ └── shelly_init.cpp ├── ShellyPlus1 │ └── shelly_init.cpp ├── ShellyPlus1PM │ └── shelly_init.cpp ├── ShellyPlus2PM │ └── shelly_init.cpp ├── ShellyPlusI4 │ └── shelly_init.cpp ├── ShellyPlusPlugS │ └── shelly_init.cpp ├── ShellyRGBW2 │ └── shelly_init.cpp ├── ShellyT32 │ └── shelly_init.cpp ├── ShellyU │ └── shelly_init.cpp ├── ShellyU25 │ └── shelly_init.cpp ├── ShellyUNI │ └── shelly_init.cpp ├── ShellyVintage │ └── shelly_init.cpp ├── mock │ ├── pwm │ │ ├── mgos_pwm.c │ │ └── mgos_pwm.h │ ├── shelly_mock.hpp │ ├── shelly_mock_pm.cpp │ ├── shelly_mock_pm.hpp │ ├── shelly_mock_rpc_service.cpp │ ├── shelly_mock_temp_sensor.cpp │ ├── shelly_mock_temp_sensor.hpp │ └── wifi_config │ │ └── shelly_wifi_config_impl.cpp ├── noisy_input_pin │ └── shelly_noisy_input_pin.cpp ├── shelly_cct_controller.cpp ├── shelly_cct_controller.hpp ├── shelly_common.hpp ├── shelly_component.cpp ├── shelly_component.hpp ├── shelly_debug.cpp ├── shelly_debug.hpp ├── shelly_hap_adaptive_lighting.cpp ├── shelly_hap_adaptive_lighting.hpp ├── shelly_hap_carbon_dioxide_sensor.cpp ├── shelly_hap_carbon_dioxide_sensor.hpp ├── shelly_hap_carbon_monoxide_sensor.cpp ├── shelly_hap_carbon_monoxide_sensor.hpp ├── shelly_hap_contact_sensor.cpp ├── shelly_hap_contact_sensor.hpp ├── shelly_hap_doorbell.cpp ├── shelly_hap_doorbell.hpp ├── shelly_hap_garage_door_opener.cpp ├── shelly_hap_garage_door_opener.hpp ├── shelly_hap_humidity_sensor.cpp ├── shelly_hap_humidity_sensor.hpp ├── shelly_hap_input.cpp ├── shelly_hap_input.hpp ├── shelly_hap_leak_sensor.cpp ├── shelly_hap_leak_sensor.hpp ├── shelly_hap_light_bulb.cpp ├── shelly_hap_light_bulb.hpp ├── shelly_hap_lock.cpp ├── shelly_hap_lock.hpp ├── shelly_hap_motion_sensor.cpp ├── shelly_hap_motion_sensor.hpp ├── shelly_hap_occupancy_sensor.cpp ├── shelly_hap_occupancy_sensor.hpp ├── shelly_hap_outlet.cpp ├── shelly_hap_outlet.hpp ├── shelly_hap_sensor_base.cpp ├── shelly_hap_sensor_base.hpp ├── shelly_hap_smoke_sensor.cpp ├── shelly_hap_smoke_sensor.hpp ├── shelly_hap_stateless_switch.cpp ├── shelly_hap_stateless_switch.hpp ├── shelly_hap_stateless_switch_base.cpp ├── shelly_hap_stateless_switch_base.hpp ├── shelly_hap_switch.cpp ├── shelly_hap_switch.hpp ├── shelly_hap_temperature_sensor.cpp ├── shelly_hap_temperature_sensor.hpp ├── shelly_hap_valve.cpp ├── shelly_hap_valve.hpp ├── shelly_hap_window_covering.cpp ├── shelly_hap_window_covering.hpp ├── shelly_input.cpp ├── shelly_input.hpp ├── shelly_input_pin.cpp ├── shelly_input_pin.hpp ├── shelly_light_bulb_controller.cpp ├── shelly_light_bulb_controller.hpp ├── shelly_main.cpp ├── shelly_main.hpp ├── shelly_noisy_input_pin.hpp ├── shelly_ota.cpp ├── shelly_ota.hpp ├── shelly_output.cpp ├── shelly_output.hpp ├── shelly_pm.cpp ├── shelly_pm.hpp ├── shelly_rgbw_controller.cpp ├── shelly_rgbw_controller.hpp ├── shelly_rpc_service.cpp ├── shelly_rpc_service.hpp ├── shelly_statusled.cpp ├── shelly_statusled.hpp ├── shelly_switch.cpp ├── shelly_switch.hpp ├── shelly_sys_led_btn.cpp ├── shelly_sys_led_btn.hpp ├── shelly_temp_sensor.cpp ├── shelly_temp_sensor.hpp ├── shelly_temp_sensor_ntc.cpp ├── shelly_temp_sensor_ntc.hpp ├── shelly_white_controller.cpp ├── shelly_white_controller.hpp ├── shelly_wifi_config.cpp ├── shelly_wifi_config.hpp └── wifi_config │ └── shelly_wifi_config_impl.cpp └── tools ├── flash-shelly.py └── shelly_update_server ├── .gitignore ├── README.md ├── go.mod ├── go.sum ├── main.go ├── parse_log.go ├── stock_model_map.yml └── update_handler.go /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | AllowShortFunctionsOnASingleLine: false 3 | SpaceAfterCStyleCast: true 4 | PointerBindsToType: false 5 | DerivePointerBinding: false 6 | IncludeBlocks: Preserve 7 | JavaScriptQuotes: Double 8 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/ubuntu/.devcontainer/base.Dockerfile 2 | 3 | # [Choice] Ubuntu version (use hirsuite or bionic on local arm64/Apple Silicon): hirsute, focal, bionic 4 | ARG VARIANT="22.04" 5 | FROM mcr.microsoft.com/devcontainers/base:ubuntu-${VARIANT} 6 | 7 | # [Optional] Uncomment this section to install additional OS packages. 8 | RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 9 | && apt-get -y install --no-install-recommends clang-format make software-properties-common 10 | RUN add-apt-repository ppa:mongoose-os/mos && apt-get update && apt-get -y install mos-latest libavahi-client3 avahi-daemon clang 11 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ubuntu", 3 | "build": { 4 | "dockerfile": "Dockerfile", 5 | "args": { 6 | "VARIANT": "22.04" 7 | } 8 | }, 9 | // Set *default* container specific settings.json values on container create. 10 | "customizations": { 11 | "vscode": { 12 | "settings": { 13 | "terminal.integrated.shell.linux": "zsh" 14 | }, 15 | // Add the IDs of extensions you want installed when the container is created. 16 | "extensions": [], 17 | "tasks": [ 18 | { 19 | "label": "Fileserver", 20 | "type": "shell", 21 | "command": "make build", 22 | "problemMatcher": [] 23 | } 24 | ] 25 | } 26 | }, 27 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 28 | // "forwardPorts": [], 29 | // Use 'postCreateCommand' to run commands after the container is created. 30 | // "postCreateCommand": "uname -a", 31 | // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. 32 | "remoteUser": "vscode", 33 | "features": { 34 | "ghcr.io/devcontainers/features/docker-in-docker:2": {}, 35 | "git": "latest" 36 | }, 37 | "postStartCommand": "sudo service dbus start; sudo service avahi-daemon start" 38 | } 39 | -------------------------------------------------------------------------------- /.github/version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import argparse 3 | import subprocess 4 | 5 | def run(*args): 6 | return subprocess.check_output(args).decode('utf-8').strip() 7 | 8 | def git_describe(*args): 9 | return run('git', 'describe', '--tags', *args) 10 | 11 | def git_branch_name(): 12 | return run('git', 'branch', '--show-current') 13 | 14 | def commits_since_forkpoint(): 15 | return int(run('git', 'rev-list', '--count', '--no-merges', 'origin/master..')) 16 | 17 | if __name__ == "__main__": 18 | parser = argparse.ArgumentParser(description='Get Shelly-HomeKit version name using Git') 19 | parser.add_argument('-s', '--suffix', action='store_true', help='output only the suffix after the version number') 20 | parser.add_argument('-r', '--release', action='store_true', help='just use tag number, for stable releases') 21 | args, extra_args = parser.parse_known_args() 22 | 23 | # all unknown command line arguments are passed directly to git-describe 24 | tag_name, commits_since_tag, extra = git_describe(*extra_args).split(sep='-', maxsplit=2) 25 | 26 | # usually this is just the sha of the git commit 27 | # however if e.g. --dirty is passed then, if working tree 28 | # dirty, it will be contained in the `info` list 29 | info = extra.split('-') 30 | 31 | version = "" if args.suffix else tag_name 32 | 33 | if args.release: 34 | print(version) 35 | exit() 36 | 37 | branch = git_branch_name() 38 | if branch == "master": 39 | version += f"-latest{commits_since_tag}" 40 | else: 41 | # strip dashes from the branch name so it doesn't mess up update 42 | version += f"-{branch.replace('-', '')}{commits_since_forkpoint()}" 43 | 44 | # append things like -dirty and -broken, 45 | # if passed, to the version name 46 | version += '-'.join(['', *info[1:]]) 47 | 48 | print(version) 49 | -------------------------------------------------------------------------------- /.github/workflows/Dockerfile-esp32-build: -------------------------------------------------------------------------------- 1 | FROM mgos/esp32-build:4.4.1-r7 2 | 3 | RUN chmod o+rx /opt/Espressif 4 | -------------------------------------------------------------------------------- /.github/workflows/Dockerfile-mos: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y -q software-properties-common && add-apt-repository -y ppa:mongoose-os/mos && \ 5 | apt -q install -y mos-latest docker.io make git && \ 6 | apt-get clean && \ 7 | rm -rf /var/lib/apt/lists/* 8 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: build-shelly-homekit 2 | on: 3 | push: 4 | pull_request: 5 | jobs: 6 | build: 7 | name: Build ${{ matrix.model }} 8 | runs-on: ubuntu-latest 9 | container: 10 | image: ghcr.io/markirb/mos:latest 11 | volumes: 12 | - /home/runner/work:/home/runner/work 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | model: 17 | - Shelly1 18 | - Shelly1Gen3 19 | - Shelly1L 20 | - Shelly1PM 21 | - Shelly1PMGen3 22 | - Shelly2 23 | - Shelly25 24 | - Shelly2PMGen3 25 | - ShellyColorBulb 26 | - ShellyDuo 27 | - ShellyI3 28 | - ShellyI4Gen3 29 | - ShellyMini1Gen3 30 | - ShellyMini1PMGen3 31 | - ShellyPlug 32 | - ShellyPlugS 33 | - ShellyPlugSGen3 34 | - ShellyPlus1 35 | - ShellyPlus1Mini 36 | - ShellyPlus1PM 37 | - ShellyPlus1PMMini 38 | - ShellyPlus2PM 39 | - ShellyPlusI4 40 | - ShellyPlusPlugS 41 | - ShellyPlusRGBWPM 42 | - ShellyPlusUni 43 | - ShellyRGBW2 44 | - ShellyUNI 45 | - ShellyVintage 46 | steps: 47 | - name: Checkout code 48 | uses: actions/checkout@v4 49 | with: 50 | fetch-depth: 0 51 | - name: Build 52 | run: | 53 | cd /home/runner/work/shelly-homekit/shelly-homekit 54 | git config --global --add safe.directory /home/runner/work/shelly-homekit/shelly-homekit 55 | make ${{ matrix.model }} LOCAL=1 RELEASE=1 RELEASE_SUFFIX=$(.github/version.py --suffix) 56 | - name: Upload firmware artifacts 57 | uses: actions/upload-artifact@v4 58 | with: 59 | name: release-${{ matrix.model }} 60 | path: releases/**/shelly-homekit-${{ matrix.model }}.zip 61 | if-no-files-found: warn 62 | merge: 63 | needs: build 64 | runs-on: ubuntu-latest 65 | steps: 66 | - name: Merge Artifacts 67 | uses: actions/upload-artifact/merge@v4 68 | with: 69 | name: all-releases 70 | pattern: release-* 71 | -------------------------------------------------------------------------------- /.github/workflows/check-format.yaml: -------------------------------------------------------------------------------- 1 | name: check format 2 | on: 3 | push: 4 | pull_request: 5 | jobs: 6 | check-format: 7 | runs-on: ubuntu-22.04 8 | steps: 9 | - name: Checkout code 10 | uses: actions/checkout@v4 11 | with: 12 | fetch-depth: 0 13 | - name: Check formatting 14 | run: make check-format 15 | -------------------------------------------------------------------------------- /.github/workflows/howto.build: -------------------------------------------------------------------------------- 1 | 2 | image=ghcr.io/markirb/esp32-build:4.4.1-r7 3 | docker build -t $image -f Dockerfile-esp32-build . 4 | docker push $image 5 | 6 | image=ghcr.io/markirb/mos:latest 7 | docker build -t $image -f Dockerfile-mos . 8 | docker push $image 9 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues. 2 | 3 | on: 4 | schedule: 5 | - cron: "30 1 * * *" 6 | 7 | jobs: 8 | stale: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/stale@v3 14 | with: 15 | repo-token: ${{ secrets.GITHUB_TOKEN }} 16 | exempt-all-pr-milestones: true 17 | exempt-issue-labels: 'enhancement, new-device-support, new-HAP-type, confirmed-bug, waiting-for-rojer, needs deeper look' 18 | stale-issue-message: 'This issue is stale because it has been open 3 weeks with no activity. Comment or this will be closed in 1 week.' 19 | stale-issue-label: 'stale' 20 | close-issue-message: 'This issue has now been closed, as no update was provided after it was marked stale. Feel free to provide updates to reopen this issue.' 21 | days-before-issue-stale: 21 22 | days-before-issue-close: 7 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | binlibs/ 2 | build/ 3 | build_*/ 4 | deps/ 5 | releases/ 6 | .vscode/ 7 | .DS_Store 8 | core-* 9 | *.gz 10 | *.zip 11 | fs/conf*.json 12 | flash-shelly.auth.yaml 13 | *.cfg.yaml 14 | .venv 15 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # Shelly-HomeKit authors 2 | 3 | The following people have contributed to the project (in chronological order): 4 | 5 | * [Deomid "rojer" Ryabkov](https://github.com/rojer) 6 | * [Andy Blackburn](https://github.com/andyblac) 7 | * [Thorsten Eurich](https://github.com/eurich) 8 | * [Dominik Schemhaus](https://github.com/schemhad) 9 | * [Timothy Langer](https://github.com/ZeeVox) 10 | * [Timo Schilling](https://github.com/timoschilling) 11 | * [Josef Blösl](https://github.com/jobl1978) 12 | * [Markus Kirberg](https://github.com/markirb) 13 | 14 | Full list of contributors [here](https://github.com/mongoose-os-apps/shelly-homekit/graphs/contributors). 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Shelly-HomeKit Contributors 2 | All rights reserved 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | -------------------------------------------------------------------------------- /docs/SDNT1608-0.1-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mongoose-os-apps/shelly-homekit/4569119f20bcad1dafa9d30102973c1657e7f68d/docs/SDNT1608-0.1-10.png -------------------------------------------------------------------------------- /fs/favicon.ico.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mongoose-os-apps/shelly-homekit/4569119f20bcad1dafa9d30102973c1657e7f68d/fs/favicon.ico.gz -------------------------------------------------------------------------------- /fs_src/logo.svg: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /fs_src/sha256.js: -------------------------------------------------------------------------------- 1 | // https://github.com/geraintluff/sha256; Public Domain 2 | let sha256 = function a(b){function c(a,b){return a>>>b|a<<32-b}for(var d,e,f=Math.pow,g=f(2,32),h="length",i="",j=[],k=8*b[h],l=a.h=a.h||[],m=a.k=a.k||[],n=m[h],o={},p=2;64>n;p++)if(!o[p]){for(d=0;313>d;d+=p)o[d]=p;l[n]=f(p,.5)*g|0,m[n++]=f(p,1/3)*g|0}for(b+="\x80";b[h]%64-56;)b+="\x00";for(d=0;d>8)return;j[d>>2]|=e<<(3-d)%4*8}for(j[j[h]]=k/g|0,j[j[h]]=k,e=0;ed;d++){var s=q[d-15],t=q[d-2],u=l[0],v=l[4],w=l[7]+(c(v,6)^c(v,11)^c(v,25))+(v&l[5]^~v&l[6])+m[d]+(q[d]=16>d?q[d]:q[d-16]+(c(s,7)^c(s,18)^s>>>3)+q[d-7]+(c(t,17)^c(t,19)^t>>>10)|0),x=(c(u,2)^c(u,13)^c(u,22))+(u&l[1]^u&l[2]^l[1]&l[2]);l=[w+x|0].concat(l),l[4]=l[4]+w|0}for(d=0;8>d;d++)l[d]=l[d]+r[d]|0}for(d=0;8>d;d++)for(e=3;e+1;e--){var y=l[d]>>8*e&255;i+=(16>y?0:"")+y.toString(16)}return i}; 3 | -------------------------------------------------------------------------------- /libreset/include/shelly_reset.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_input.hpp" 21 | 22 | namespace shelly { 23 | 24 | // Reset device WiFi and auth settings. 25 | void ResetDevice(int out_gpio); 26 | 27 | // Wipe all device configuration, including WiFi. 28 | bool WipeDevice(); 29 | 30 | // Wipe device before reverting to stock FW. 31 | // Preserves WiFi STA config. 32 | void WipeDeviceRevertToStock(); 33 | 34 | // Handler for input reset sequence. 35 | void HandleInputResetSequence(Input *in, int out_gpio, Input::Event ev, 36 | bool cur_state); 37 | 38 | bool IsSoftReboot(); 39 | 40 | bool IsFailsafeMode(); 41 | 42 | void SanitizeSysConfig(); 43 | 44 | // Check if device is in a reboot loop (deliberate or not) and perform reset. 45 | void CheckRebootCounter(); 46 | 47 | } // namespace shelly 48 | -------------------------------------------------------------------------------- /libreset/mos.yml: -------------------------------------------------------------------------------- 1 | description: Shelly device reset library 2 | type: lib 3 | version: 1.0.0 4 | 5 | sources: 6 | - src 7 | 8 | includes: 9 | - include 10 | 11 | no_implicit_init_deps: true 12 | # Execute as early as possible, before pretty much anything else. 13 | init_after: 14 | - core 15 | init_before: 16 | - adc 17 | - i2c 18 | - file-logger 19 | - homekit-adk 20 | - http-server 21 | - ota-http-server 22 | - rpc-* 23 | - wifi 24 | 25 | manifest_version: 2019-07-28 26 | -------------------------------------------------------------------------------- /src/ADE7953/shelly_pm_ade7953.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_pm_ade7953.hpp" 19 | 20 | #include 21 | 22 | #include "mgos.hpp" 23 | #include "mgos_ade7953.h" 24 | 25 | namespace shelly { 26 | 27 | struct mgos_ade7953 *s_ade7953 = NULL; 28 | 29 | ADE7953PowerMeter::ADE7953PowerMeter(int id, struct mgos_ade7953 *ade7953, 30 | int channel) 31 | : PowerMeter(id), 32 | ade7953_(ade7953), 33 | channel_(channel), 34 | acc_timer_(std::bind(&ADE7953PowerMeter::AEAAccumulateTimerCB, this)) { 35 | } 36 | 37 | ADE7953PowerMeter::~ADE7953PowerMeter() { 38 | } 39 | 40 | Status ADE7953PowerMeter::Init() { 41 | acc_timer_.Reset(10000, MGOS_TIMER_REPEAT); 42 | return Status::OK(); 43 | } 44 | 45 | StatusOr ADE7953PowerMeter::GetPowerW() { 46 | float apa = 0; 47 | if (!mgos_ade7953_get_apower(ade7953_, channel_, &apa)) { 48 | return mgos::Errorf(STATUS_UNAVAILABLE, "Failed to read %s", "AP"); 49 | } 50 | apa = std::fabs(apa); 51 | if (apa < 1) apa = 0; // Suppress noise. 52 | return apa; 53 | } 54 | 55 | StatusOr ADE7953PowerMeter::GetEnergyWH() { 56 | return GetEnergyWH(false /* reset */); 57 | } 58 | 59 | StatusOr ADE7953PowerMeter::GetEnergyWH(bool reset) { 60 | float aea = 0; 61 | if (!mgos_ade7953_get_aenergy(ade7953_, channel_, reset, &aea)) { 62 | return mgos::Errorf(STATUS_UNAVAILABLE, "Failed to read %s", "AE"); 63 | } 64 | float res = aea_acc_ + std::fabs(aea); 65 | if (reset) { 66 | aea_acc_ = res; 67 | } 68 | return res; 69 | } 70 | 71 | void ADE7953PowerMeter::AEAAccumulateTimerCB() { 72 | GetEnergyWH(true /* reset */); 73 | } 74 | 75 | } // namespace shelly 76 | -------------------------------------------------------------------------------- /src/ADE7953/shelly_pm_ade7953.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_pm.hpp" 19 | 20 | #include 21 | 22 | #include "mgos.hpp" 23 | #include "mgos_ade7953.h" 24 | 25 | namespace shelly { 26 | 27 | class ADE7953PowerMeter : public PowerMeter { 28 | public: 29 | ADE7953PowerMeter(int id, struct mgos_ade7953 *ade7953, int channel); 30 | virtual ~ADE7953PowerMeter(); 31 | 32 | Status Init() override; 33 | StatusOr GetPowerW() override; 34 | StatusOr GetEnergyWH() override; 35 | 36 | private: 37 | StatusOr GetEnergyWH(bool reset); 38 | void AEAAccumulateTimerCB(); 39 | 40 | struct mgos_ade7953 *const ade7953_; 41 | const int channel_; 42 | float aea_acc_ = 0; // Accumulated active energy. 43 | mgos::Timer acc_timer_; 44 | }; 45 | 46 | } // namespace shelly 47 | -------------------------------------------------------------------------------- /src/BL0937/shelly_pm_bl0937.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_pm.hpp" 19 | 20 | #include "mgos_timers.hpp" 21 | 22 | namespace shelly { 23 | 24 | class BL0937PowerMeter : public PowerMeter { 25 | public: 26 | BL0937PowerMeter(int id, int cf_pin, int cf1_pin, int sel_pin, int meas_time, 27 | float apc); 28 | virtual ~BL0937PowerMeter(); 29 | 30 | Status Init() override; 31 | StatusOr GetPowerW() override; 32 | StatusOr GetEnergyWH() override; 33 | 34 | private: 35 | static void GPIOIntHandler(int pin, void *arg); 36 | void MeasureTimerCB(); 37 | 38 | const int cf_pin_, cf1_pin_, sel_pin_, meas_time_; 39 | const float apc_; 40 | 41 | volatile uint32_t cf_count_ = 0, cf1_count_ = 0; 42 | int64_t meas_start_ = 0; 43 | 44 | float apa_ = 0; // Last active power reading, W. 45 | float aea_ = 0; // Accumulated active energy, Wh. 46 | 47 | mgos::Timer meas_timer_; 48 | }; 49 | 50 | } // namespace shelly 51 | -------------------------------------------------------------------------------- /src/BL0942/shelly_pm_bl0942.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_pm.hpp" 19 | 20 | #include "mgos_timers.hpp" 21 | 22 | namespace shelly { 23 | 24 | struct bl0942_cfg { 25 | float voltage_scale; 26 | float current_scale; 27 | float apower_scale; 28 | float aenergy_scale; 29 | }; 30 | 31 | class BL0942PowerMeter : public PowerMeter { 32 | public: 33 | BL0942PowerMeter(int id, int tx_pin, int rx_pin, int meas_time, int uart_no, 34 | const bl0942_cfg &cfg); 35 | virtual ~BL0942PowerMeter(); 36 | 37 | Status Init() override; 38 | StatusOr GetPowerW() override; 39 | StatusOr GetEnergyWH() override; 40 | 41 | private: 42 | void MeasureTimerCB(); 43 | 44 | const int tx_pin_, rx_pin_, meas_time_, uart_no_; 45 | const bl0942_cfg cfg_; 46 | 47 | float apa_ = 0; // Last active power reading, W. 48 | float aea_ = 0; // Accumulated active energy, Wh. 49 | // 50 | bool ReadReg(uint8_t reg, uint8_t *rx_buf, size_t len); 51 | bool WriteReg(uint8_t reg, uint32_t val); 52 | 53 | mgos::Timer meas_timer_; 54 | }; 55 | 56 | } // namespace shelly 57 | -------------------------------------------------------------------------------- /src/DHT/shelly_dht_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_dht_sensor.hpp" 19 | #include 20 | #include "mgos_hal.h" 21 | 22 | namespace shelly { 23 | 24 | std::vector> DiscoverDHTSensors(int in, int out) { 25 | std::vector> sensors; 26 | 27 | std::unique_ptr dht(new DHTSensor(in, out)); 28 | auto status = dht->Init(); 29 | if (status == Status::OK()) { 30 | sensors.push_back(std::move(dht)); 31 | } else { 32 | LOG(LL_ERROR, ("dht init failed: %s", status.ToString().c_str())); 33 | } 34 | return sensors; 35 | } 36 | 37 | DHTSensor::DHTSensor(uint8_t pin_in, uint8_t pin_out) 38 | : pin_in_(pin_in), 39 | pin_out_(pin_out), 40 | meas_timer_(std::bind(&DHTSensor::UpdateTemperatureCB, this)) { 41 | result_ = mgos::Errorf(STATUS_UNAVAILABLE, "Not updated yet"); 42 | result_humidity_ = mgos::Errorf(STATUS_UNAVAILABLE, "Not updated yet"); 43 | } 44 | 45 | DHTSensor::~DHTSensor() { 46 | } 47 | 48 | Status DHTSensor::Init() { 49 | dht = mgos_dht_create_separate_io(pin_in_, pin_out_, DHT21); 50 | 51 | if (dht == NULL) { 52 | return mgos::Errorf(STATUS_NOT_FOUND, "dht sensor init unsuccesfull"); 53 | } 54 | 55 | size_t tries = 56 | 2; // first read was observed to be not successfull, reason unknown 57 | mgos_dht_stats stats; 58 | for (size_t i = 0; i < tries; i++) { 59 | result_ = mgos_dht_get_temp(dht); 60 | if (mgos_dht_getStats(dht, &stats)) { 61 | if (stats.read_success >= 1) { 62 | return Status::OK(); 63 | } else if (i != (tries - 1)) { 64 | mgos_msleep(2 * 65 | 1000); // try again after wait time of MGOs_DHT_READ_DELAY 66 | } 67 | } 68 | } 69 | 70 | return mgos::Errorf(STATUS_NOT_FOUND, "No DHT Sensor found"); 71 | } 72 | 73 | void DHTSensor::StartUpdating(int interval) { 74 | meas_timer_.Reset(interval, MGOS_TIMER_REPEAT | MGOS_TIMER_RUN_NOW); 75 | } 76 | 77 | void DHTSensor::StopUpdating() { 78 | meas_timer_.Clear(); 79 | } 80 | 81 | StatusOr DHTSensor::GetTemperature() { 82 | return result_; 83 | } 84 | 85 | StatusOr DHTSensor::GetHumidity() { 86 | return result_humidity_; 87 | } 88 | 89 | void DHTSensor::UpdateTemperatureCB() { 90 | float result = mgos_dht_get_temp(dht); 91 | float result_humidity = mgos_dht_get_humidity(dht); 92 | 93 | // check values for validity 94 | if (((result == 0) and (result_humidity == 0)) or isnan(result) or 95 | isnan(result_humidity)) { 96 | // error during readout do nothing for now 97 | LOG(LL_INFO, ("DHT: invalid value received")); 98 | return; 99 | } 100 | 101 | result_ = result; 102 | result_humidity_ = result_humidity; 103 | 104 | if (notifier_) { 105 | notifier_(); 106 | } 107 | if (notifier_hum_) { 108 | notifier_hum_(); 109 | } 110 | } 111 | 112 | } // namespace shelly 113 | -------------------------------------------------------------------------------- /src/DHT/shelly_dht_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_temp_sensor.hpp" 21 | 22 | #include "mgos_timers.hpp" 23 | 24 | #include 25 | 26 | #include 27 | 28 | namespace shelly { 29 | 30 | std::vector> DiscoverDHTSensors(int in, int out); 31 | 32 | class DHTSensor : public HumidityTempSensor { 33 | public: 34 | DHTSensor(uint8_t pin_in, uint8_t pin_out); 35 | virtual ~DHTSensor(); 36 | 37 | Status Init(); 38 | StatusOr GetTemperature() override; 39 | StatusOr GetHumidity() override; 40 | 41 | virtual void StartUpdating(int interval) override; 42 | virtual void StopUpdating() override; 43 | 44 | private: 45 | uint8_t pin_in_; 46 | uint8_t pin_out_; 47 | 48 | mgos::Timer meas_timer_; 49 | 50 | mgos_dht *dht; 51 | 52 | void UpdateTemperatureCB(); 53 | StatusOr result_; 54 | StatusOr result_humidity_; 55 | }; 56 | 57 | } // namespace shelly 58 | -------------------------------------------------------------------------------- /src/DS18XXX/shelly_temp_sensor_ow.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_temp_sensor.hpp" 21 | 22 | #include 23 | 24 | #include "mgos_timers.hpp" 25 | 26 | struct mgos_onewire; 27 | 28 | namespace shelly { 29 | 30 | class Onewire { 31 | public: 32 | struct ROM { 33 | uint64_t family : 8; 34 | uint64_t serial : 48; 35 | uint64_t crc : 8; 36 | 37 | ROM() : family(0), serial(0), crc(0) { 38 | } 39 | }; 40 | 41 | Onewire(int pin_in, int pin_out); 42 | ~Onewire(); 43 | struct mgos_onewire *Get(); 44 | std::vector> DiscoverAll(); 45 | 46 | private: 47 | struct mgos_onewire *ow_; 48 | 49 | int pin_out_; 50 | std::unique_ptr NextAvailableSensor(int type); 51 | }; 52 | 53 | class TempSensorDS18XXX : public TempSensor { 54 | public: 55 | TempSensorDS18XXX(struct mgos_onewire *ow, const Onewire::ROM &rom); 56 | virtual ~TempSensorDS18XXX(); 57 | 58 | Status Init(); 59 | StatusOr GetTemperature() override; 60 | 61 | static bool SupportsFamily(uint8_t family); 62 | virtual void StartUpdating(int interval) override; 63 | virtual void StopUpdating() override; 64 | 65 | private: 66 | struct __attribute__((__packed__)) Scratchpad { 67 | int16_t temperature; 68 | uint8_t th; 69 | uint8_t tl; 70 | union { 71 | uint8_t rsvd_1 : 5; 72 | uint8_t resolution : 2; 73 | uint8_t rsvd_0 : 1; 74 | uint8_t val; 75 | } cfg; 76 | uint8_t rfu; 77 | uint8_t count_remain; 78 | uint8_t count_per_c; 79 | uint8_t crc; 80 | 81 | int GetResolution() const; 82 | int GetConversionTimeMs() const; 83 | }; 84 | 85 | void ReadTemperatureCB(); 86 | void UpdateTemperatureCB(); 87 | 88 | StatusOr ReadScratchpad(); 89 | bool ReadPowerSupply(); 90 | 91 | struct mgos_onewire *ow_ = nullptr; 92 | const Onewire::ROM rom_; 93 | StatusOr result_; 94 | 95 | mgos::Timer meas_timer_; 96 | mgos::Timer read_timer_; 97 | int conversion_time_ms_ = 750; 98 | }; 99 | 100 | } // namespace shelly 101 | -------------------------------------------------------------------------------- /src/Shelly1/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "mgos_hap.h" 19 | 20 | #include "shelly_dht_sensor.hpp" 21 | #include "shelly_hap_garage_door_opener.hpp" 22 | #include "shelly_hap_input.hpp" 23 | #include "shelly_input_pin.hpp" 24 | #include "shelly_main.hpp" 25 | #include "shelly_temp_sensor_ow.hpp" 26 | 27 | namespace shelly { 28 | 29 | static std::unique_ptr s_onewire; 30 | static std::vector> sensors; 31 | 32 | void CreatePeripherals(std::vector> *inputs, 33 | std::vector> *outputs, 34 | std::vector> *pms UNUSED_ARG, 35 | std::unique_ptr *sys_temp UNUSED_ARG) { 36 | outputs->emplace_back(new OutputPin(1, 4, 1)); 37 | auto *in1 = new InputPin(1, 5, 1, MGOS_GPIO_PULL_NONE, true); 38 | in1->AddHandler(std::bind(&HandleInputResetSequence, in1, 4, _1, _2)); 39 | in1->Init(); 40 | inputs->emplace_back(in1); 41 | 42 | int pin_in = 3; 43 | int pin_out = 0; 44 | 45 | if (DetectAddon(pin_in, pin_out)) { 46 | s_onewire.reset(new Onewire(pin_in, pin_out)); 47 | sensors = s_onewire->DiscoverAll(); 48 | if (sensors.empty()) { 49 | s_onewire.reset(); 50 | sensors = DiscoverDHTSensors(pin_in, pin_out); 51 | } 52 | if (sensors.empty()) { 53 | // No sensors detected, we assume to use addon as input for switch or 54 | // closed/open sensor 55 | auto *in2 = new InputPin(2, pin_in, 0, MGOS_GPIO_PULL_NONE, false); 56 | in2->Init(); 57 | inputs->emplace_back(in2); 58 | } 59 | } 60 | } 61 | 62 | void CreateComponents(std::vector> *comps, 63 | std::vector> *accs, 64 | HAPAccessoryServerRef *svr) { 65 | bool gdo_mode = mgos_sys_config_get_shelly_mode() == (int) Mode::kGarageDoor; 66 | bool ext_sensor_switch = (FindInput(2) != nullptr); 67 | bool addon_input = !gdo_mode && ext_sensor_switch; 68 | bool single_accessory = 69 | sensors.empty() && !addon_input && 70 | (mgos_sys_config_get_sw1_in_mode() != (int) InMode::kDetached); 71 | if (gdo_mode) { 72 | hap::CreateHAPGDO(1, FindInput(1), FindInput(2), FindOutput(1), 73 | FindOutput(1), mgos_sys_config_get_gdo1(), comps, accs, 74 | svr, true); 75 | } else { 76 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 77 | comps, accs, svr, single_accessory); 78 | } 79 | 80 | if (!sensors.empty()) { 81 | CreateHAPSensors(&sensors, comps, accs, svr); 82 | } else if (addon_input) { 83 | hap::CreateHAPInput(2, mgos_sys_config_get_in2(), comps, accs, svr); 84 | } 85 | } 86 | 87 | } // namespace shelly 88 | -------------------------------------------------------------------------------- /src/Shelly1L/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_input.hpp" 19 | #include "shelly_input.hpp" 20 | #include "shelly_main.hpp" 21 | #include "shelly_noisy_input_pin.hpp" 22 | #include "shelly_pm_bl0937.hpp" 23 | #include "shelly_switch.hpp" 24 | #include "shelly_sys_led_btn.hpp" 25 | #include "shelly_temp_sensor_ntc.hpp" 26 | 27 | namespace shelly { 28 | 29 | void CreatePeripherals(std::vector> *inputs, 30 | std::vector> *outputs, 31 | std::vector> *pms, 32 | std::unique_ptr *sys_temp) { 33 | outputs->emplace_back(new OutputPin(1, 5, 1)); 34 | auto *in1 = new NoisyInputPin(1, 4, 1, MGOS_GPIO_PULL_NONE, true); 35 | in1->AddHandler(std::bind(&HandleInputResetSequence, in1, 5, _1, _2)); 36 | in1->Init(); 37 | inputs->emplace_back(in1); 38 | auto *in2 = new NoisyInputPin(2, 14, 1, MGOS_GPIO_PULL_NONE, false); 39 | in2->Init(); 40 | inputs->emplace_back(in2); 41 | #if 0 // 1L uses BL0937 in current-only mode. This is not yet supported. 42 | std::unique_ptr pm(new BL0937PowerMeter(1, -1, 4, -1)); 43 | if (pm->Init().ok()) { 44 | pms->emplace_back(std::move(pm)); 45 | } 46 | #else 47 | (void) pms; 48 | #endif 49 | sys_temp->reset(new TempSensorSDNT1608X103F3950(0, 3.3f, 33000.0f)); 50 | 51 | InitSysLED(LED_GPIO, LED_ON); 52 | InitSysBtn(BTN_GPIO, BTN_DOWN); 53 | } 54 | 55 | void CreateComponents(std::vector> *comps, 56 | std::vector> *accs, 57 | HAPAccessoryServerRef *svr) { 58 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 59 | comps, accs, svr, false); 60 | if (mgos_sys_config_get_sw1_in_mode() == (int) InMode::kEdgeBoth || 61 | mgos_sys_config_get_sw1_in_mode() == (int) InMode::kActivation) { 62 | ShellySwitch *sw = reinterpret_cast(comps->back().get()); 63 | sw->AddInput(FindInput(2)); 64 | } else { 65 | hap::CreateHAPInput(2, mgos_sys_config_get_in2(), comps, accs, svr); 66 | } 67 | } 68 | 69 | } // namespace shelly 70 | -------------------------------------------------------------------------------- /src/Shelly2/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | 20 | #include "shelly_hap_garage_door_opener.hpp" 21 | #include "shelly_input_pin.hpp" 22 | #include "shelly_main.hpp" 23 | 24 | namespace shelly { 25 | 26 | void CreatePeripherals(std::vector> *inputs, 27 | std::vector> *outputs, 28 | std::vector> *pms, 29 | std::unique_ptr *sys_temp) { 30 | outputs->emplace_back(new OutputPin(1, 4, 1)); 31 | outputs->emplace_back(new OutputPin(2, 5, 1)); 32 | auto *in1 = new InputPin(1, 12, 1, MGOS_GPIO_PULL_NONE, true); 33 | in1->AddHandler(std::bind(&HandleInputResetSequence, in1, 4, _1, _2)); 34 | in1->Init(); 35 | inputs->emplace_back(in1); 36 | auto *in2 = new InputPin(2, 14, 1, MGOS_GPIO_PULL_NONE, false); 37 | in2->Init(); 38 | inputs->emplace_back(in2); 39 | (void) sys_temp; 40 | (void) pms; 41 | } 42 | 43 | void CreateComponents(std::vector> *comps, 44 | std::vector> *accs, 45 | HAPAccessoryServerRef *svr) { 46 | if (mgos_sys_config_get_shelly_mode() == (int) Mode::kGarageDoor) { 47 | hap::CreateHAPGDO(1, FindInput(1), FindInput(2), FindOutput(1), 48 | FindOutput(2), mgos_sys_config_get_gdo1(), comps, accs, 49 | svr, true /* single accessory */); 50 | return; 51 | } 52 | 53 | // Use legacy layout if upgraded from an older version (pre-2.1). 54 | // However, presence of detached inputs overrides it. 55 | bool compat_20 = (mgos_sys_config_get_shelly_legacy_hap_layout() && 56 | mgos_sys_config_get_sw1_in_mode() != 3 && 57 | mgos_sys_config_get_sw2_in_mode() != 3); 58 | if (!compat_20) { 59 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 60 | comps, accs, svr, false /* to_pri_acc */); 61 | CreateHAPSwitch(2, mgos_sys_config_get_sw2(), mgos_sys_config_get_in2(), 62 | comps, accs, svr, false /* to_pri_acc */); 63 | } else { 64 | CreateHAPSwitch(2, mgos_sys_config_get_sw2(), mgos_sys_config_get_in2(), 65 | comps, accs, svr, true /* to_pri_acc */); 66 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 67 | comps, accs, svr, true /* to_pri_acc */); 68 | std::reverse(comps->begin(), comps->end()); 69 | } 70 | } 71 | 72 | } // namespace shelly 73 | -------------------------------------------------------------------------------- /src/Shelly25/shelly_init_components.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | 20 | #include "shelly_hap_garage_door_opener.hpp" 21 | #include "shelly_hap_input.hpp" 22 | #include "shelly_hap_window_covering.hpp" 23 | #include "shelly_main.hpp" 24 | 25 | namespace shelly { 26 | 27 | void CreateComponents(std::vector> *comps, 28 | std::vector> *accs, 29 | HAPAccessoryServerRef *svr) { 30 | if (mgos_sys_config_get_shelly_mode() == (int) Mode::kRollerShutter) { 31 | hap::CreateHAPWC(1, FindInput(1), FindInput(2), FindOutput(1), 32 | FindOutput(2), FindPM(1), FindPM(2), 33 | mgos_sys_config_get_wc1(), mgos_sys_config_get_in1(), 34 | mgos_sys_config_get_in2(), comps, accs, svr); 35 | return; 36 | } 37 | 38 | if (mgos_sys_config_get_shelly_mode() == (int) Mode::kGarageDoor) { 39 | hap::CreateHAPGDO(1, FindInput(1), FindInput(2), FindOutput(1), 40 | FindOutput(2), mgos_sys_config_get_gdo1(), comps, accs, 41 | svr, true /* single accessory */); 42 | return; 43 | } 44 | // Use legacy layout if upgraded from an older version (pre-2.1). 45 | // However, presence of detached inputs overrides it. 46 | bool compat_20 = (mgos_sys_config_get_shelly_legacy_hap_layout() && 47 | mgos_sys_config_get_sw1_in_mode() != 3 && 48 | mgos_sys_config_get_sw2_in_mode() != 3); 49 | if (!compat_20) { 50 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 51 | comps, accs, svr, false /* to_pri_acc */); 52 | CreateHAPSwitch(2, mgos_sys_config_get_sw2(), mgos_sys_config_get_in2(), 53 | comps, accs, svr, false /* to_pri_acc */); 54 | } else { 55 | CreateHAPSwitch(2, mgos_sys_config_get_sw2(), mgos_sys_config_get_in2(), 56 | comps, accs, svr, true /* to_pri_acc */); 57 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 58 | comps, accs, svr, true /* to_pri_acc */); 59 | std::reverse(comps->begin(), comps->end()); 60 | } 61 | } 62 | 63 | } // namespace shelly 64 | -------------------------------------------------------------------------------- /src/ShellyColorBulb/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_cct_controller.hpp" 19 | #include "shelly_hap_input.hpp" 20 | #include "shelly_hap_light_bulb.hpp" 21 | #include "shelly_input_pin.hpp" 22 | #include "shelly_main.hpp" 23 | #include "shelly_rgbw_controller.hpp" 24 | 25 | namespace shelly { 26 | 27 | void CreatePeripherals(UNUSED_ARG std::vector> *inputs, 28 | std::vector> *outputs, 29 | UNUSED_ARG std::vector> *pms, 30 | UNUSED_ARG std::unique_ptr *sys_temp) { 31 | outputs->emplace_back(new OutputPin(1, 13, 1)); // R 32 | outputs->emplace_back(new OutputPin(2, 12, 1)); // G 33 | outputs->emplace_back(new OutputPin(3, 14, 1)); // B 34 | outputs->emplace_back(new OutputPin(4, 5, 1)); // W 35 | } 36 | 37 | void CreateComponents(std::vector> *comps, 38 | std::vector> *accs, 39 | HAPAccessoryServerRef *svr) { 40 | std::unique_ptr lightbulb_controller; 41 | std::unique_ptr hap_light; 42 | auto *lb_cfg = (struct mgos_config_lb *) mgos_sys_config_get_lb1(); 43 | 44 | lightbulb_controller.reset(new RGBWController( 45 | lb_cfg, FindOutput(1), FindOutput(2), FindOutput(3), FindOutput(4))); 46 | 47 | hap_light.reset(new hap::LightBulb( 48 | 1, nullptr, std::move(lightbulb_controller), lb_cfg, false)); 49 | 50 | if (hap_light == nullptr || !hap_light->Init().ok()) { 51 | return; 52 | } 53 | 54 | mgos::hap::Accessory *pri_acc = accs->front().get(); 55 | shelly::hap::LightBulb *light_ref = hap_light.get(); 56 | hap_light->set_primary(true); 57 | pri_acc->SetCategory(kHAPAccessoryCategory_Lighting); 58 | pri_acc->AddService(hap_light.get()); 59 | pri_acc->SetIdentifyCB( 60 | [light_ref](const HAPAccessoryIdentifyRequest *request UNUSED_ARG) { 61 | light_ref->Identify(); 62 | return kHAPError_None; 63 | }); 64 | 65 | comps->push_back(std::move(hap_light)); 66 | } 67 | } // namespace shelly -------------------------------------------------------------------------------- /src/ShellyDuo/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_cct_controller.hpp" 19 | #include "shelly_hap_input.hpp" 20 | #include "shelly_hap_light_bulb.hpp" 21 | #include "shelly_input_pin.hpp" 22 | #include "shelly_light_bulb_controller.hpp" 23 | #include "shelly_main.hpp" 24 | 25 | namespace shelly { 26 | 27 | void CreatePeripherals(UNUSED_ARG std::vector> *inputs, 28 | std::vector> *outputs, 29 | UNUSED_ARG std::vector> *pms, 30 | UNUSED_ARG std::unique_ptr *sys_temp) { 31 | outputs->emplace_back(new OutputPin(1, 5, 1)); 32 | outputs->emplace_back(new OutputPin(2, 4, 1)); 33 | } 34 | 35 | void CreateComponents(std::vector> *comps, 36 | std::vector> *accs, 37 | HAPAccessoryServerRef *svr UNUSED_ARG) { 38 | std::unique_ptr lightbulb_controller; 39 | std::unique_ptr hap_light; 40 | auto *lb_cfg = (struct mgos_config_lb *) mgos_sys_config_get_lb1(); 41 | 42 | lightbulb_controller.reset( 43 | new CCTController(lb_cfg, FindOutput(1), FindOutput(2))); 44 | 45 | hap_light.reset(new hap::LightBulb( 46 | 1, nullptr, std::move(lightbulb_controller), lb_cfg, false)); 47 | 48 | if (hap_light == nullptr || !hap_light->Init().ok()) { 49 | return; 50 | } 51 | 52 | // Use adaptive lightning when possible (CCT) 53 | std::unique_ptr adaptive_light; 54 | adaptive_light.reset(new hap::AdaptiveLighting(hap_light.get(), lb_cfg)); 55 | auto st = adaptive_light->Init(); 56 | if (st.ok()) { 57 | hap_light->SetAdaptiveLight(std::move(adaptive_light)); 58 | } 59 | 60 | mgos::hap::Accessory *pri_acc = accs->front().get(); 61 | shelly::hap::LightBulb *light_ref = hap_light.get(); 62 | hap_light->set_primary(true); 63 | pri_acc->SetCategory(kHAPAccessoryCategory_Lighting); 64 | pri_acc->AddService(hap_light.get()); 65 | pri_acc->SetIdentifyCB( 66 | [light_ref](const HAPAccessoryIdentifyRequest *request UNUSED_ARG) { 67 | light_ref->Identify(); 68 | return kHAPError_None; 69 | }); 70 | 71 | comps->push_back(std::move(hap_light)); 72 | } 73 | } // namespace shelly 74 | -------------------------------------------------------------------------------- /src/ShellyI3/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_input.hpp" 19 | #include "shelly_hap_stateless_switch.hpp" 20 | #include "shelly_main.hpp" 21 | #include "shelly_noisy_input_pin.hpp" 22 | #include "shelly_sys_led_btn.hpp" 23 | #include "shelly_temp_sensor_ntc.hpp" 24 | 25 | namespace shelly { 26 | 27 | // i3 inputs are super noisy and cause interrupt storm. 28 | // Instead we run a frequent hardware timer that smoothes things out. 29 | void CreatePeripherals(std::vector> *inputs, 30 | std::vector> *outputs, 31 | std::vector> *pms UNUSED_ARG, 32 | std::unique_ptr *sys_temp) { 33 | auto *in1 = new NoisyInputPin(1, 14, 1, MGOS_GPIO_PULL_NONE, true); 34 | in1->AddHandler(std::bind(&HandleInputResetSequence, in1, -1, _1, _2)); 35 | inputs->emplace_back(in1); 36 | in1->Init(); 37 | 38 | auto *in2 = new NoisyInputPin(2, 12, 1, MGOS_GPIO_PULL_NONE, false); 39 | inputs->emplace_back(in2); 40 | in2->Init(); 41 | 42 | auto *in3 = new NoisyInputPin(3, 13, 1, MGOS_GPIO_PULL_NONE, false); 43 | inputs->emplace_back(in3); 44 | in3->Init(); 45 | 46 | sys_temp->reset(new TempSensorSDNT1608X103F3950(0, 3.3f, 33000.0f)); 47 | 48 | InitSysLED(LED_GPIO, LED_ON); 49 | InitSysBtn(BTN_GPIO, BTN_DOWN); 50 | } 51 | 52 | void CreateComponents(std::vector> *comps, 53 | std::vector> *accs, 54 | HAPAccessoryServerRef *svr) { 55 | hap::CreateHAPInput(1, mgos_sys_config_get_in1(), comps, accs, svr); 56 | hap::CreateHAPInput(2, mgos_sys_config_get_in2(), comps, accs, svr); 57 | hap::CreateHAPInput(3, mgos_sys_config_get_in3(), comps, accs, svr); 58 | } 59 | 60 | } // namespace shelly 61 | -------------------------------------------------------------------------------- /src/ShellyMini1Gen3/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_garage_door_opener.hpp" 19 | #include "shelly_hap_input.hpp" 20 | #include "shelly_input_pin.hpp" 21 | #include "shelly_main.hpp" 22 | #include "shelly_sys_led_btn.hpp" 23 | #include "shelly_temp_sensor_ntc.hpp" 24 | 25 | namespace shelly { 26 | 27 | void CreatePeripherals(std::vector> *inputs, 28 | std::vector> *outputs, 29 | std::vector> *pms UNUSED_ARG, 30 | std::unique_ptr *sys_temp) { 31 | outputs->emplace_back(new OutputPin(1, 7, 1)); 32 | 33 | auto *in = new InputPin(1, 10, 1, MGOS_GPIO_PULL_NONE, true); 34 | in->AddHandler(std::bind(&HandleInputResetSequence, in, LED_GPIO, _1, _2)); 35 | in->Init(); 36 | inputs->emplace_back(in); 37 | 38 | // not yet compatible 39 | #ifdef MGOS_HAVE_ADC 40 | sys_temp->reset(new TempSensorSDNT1608X103F3950(3, 3.3f, 10000.0f)); 41 | #endif 42 | 43 | InitSysLED(LED_GPIO, LED_ON); 44 | InitSysBtn(BTN_GPIO, BTN_DOWN); 45 | } 46 | 47 | void CreateComponents(std::vector> *comps, 48 | std::vector> *accs, 49 | HAPAccessoryServerRef *svr) { 50 | bool gdo_mode = mgos_sys_config_get_shelly_mode() == (int) Mode::kGarageDoor; 51 | if (gdo_mode) { 52 | hap::CreateHAPGDO(1, FindInput(1), FindInput(2), FindOutput(1), 53 | FindOutput(1), mgos_sys_config_get_gdo1(), comps, accs, 54 | svr, true); 55 | } else { 56 | CreateHAPSwitch( 57 | 1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), comps, accs, 58 | svr, mgos_sys_config_get_sw1_in_mode() != (int) InMode::kDetached); 59 | } 60 | } 61 | 62 | } // namespace shelly 63 | -------------------------------------------------------------------------------- /src/ShellyMini1PMGen3/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_garage_door_opener.hpp" 19 | #include "shelly_hap_input.hpp" 20 | #include "shelly_input_pin.hpp" 21 | #include "shelly_main.hpp" 22 | #include "shelly_pm_bl0942.hpp" 23 | #include "shelly_sys_led_btn.hpp" 24 | #include "shelly_temp_sensor_ntc.hpp" 25 | 26 | namespace shelly { 27 | 28 | void CreatePeripherals(std::vector> *inputs, 29 | std::vector> *outputs, 30 | std::vector> *pms UNUSED_ARG, 31 | std::unique_ptr *sys_temp) { 32 | outputs->emplace_back(new OutputPin(1, 5, 1)); 33 | 34 | auto *in = new InputPin(1, 10, 1, MGOS_GPIO_PULL_NONE, true); 35 | in->AddHandler(std::bind(&HandleInputResetSequence, in, LED_GPIO, _1, _2)); 36 | in->Init(); 37 | inputs->emplace_back(in); 38 | 39 | #ifdef MGOS_HAVE_ADC 40 | sys_temp->reset(new TempSensorSDNT1608X103F3950(3, 3.3f, 10000.0f)); 41 | #endif 42 | 43 | struct bl0942_cfg cfg = { 44 | .voltage_scale = (73989 / (1.218 * 4)), 45 | .current_scale = (305978 / (1.218)), 46 | .apower_scale = (3537 / (1.218 * 1.218 * 4)), 47 | .aenergy_scale = ((3537 / (1.218 * 1.218 * 4)) * 3600 / (1638.4 * 256))}; 48 | 49 | mgos_config_factory *c = &(mgos_sys_config.factory); 50 | if (c->calib.done) { 51 | mgos_config_scales *g = &c->calib.scales0; 52 | cfg.voltage_scale = g->voltage_scale / 500; 53 | cfg.current_scale = g->current_scale / 2; 54 | cfg.apower_scale = 1e11 / g->apower_scale; 55 | cfg.aenergy_scale = 1e11 / g->aenergy_scale; 56 | } 57 | 58 | std::unique_ptr pm(new BL0942PowerMeter(1, 6, 7, 1, 1, cfg)); 59 | // BL0942 GPIO6 TX GPIO7 RX 60 | const Status &st = pm->Init(); 61 | if (st.ok()) { 62 | pms->emplace_back(std::move(pm)); 63 | } else { 64 | const std::string &s = st.ToString(); 65 | LOG(LL_ERROR, ("PM init failed: %s", s.c_str())); 66 | } 67 | 68 | InitSysLED(LED_GPIO, LED_ON); 69 | InitSysBtn(BTN_GPIO, BTN_DOWN); 70 | } 71 | 72 | void CreateComponents(std::vector> *comps, 73 | std::vector> *accs, 74 | HAPAccessoryServerRef *svr) { 75 | bool gdo_mode = mgos_sys_config_get_shelly_mode() == (int) Mode::kGarageDoor; 76 | if (gdo_mode) { 77 | hap::CreateHAPGDO(1, FindInput(1), FindInput(2), FindOutput(1), 78 | FindOutput(1), mgos_sys_config_get_gdo1(), comps, accs, 79 | svr, true); 80 | } else { 81 | CreateHAPSwitch( 82 | 1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), comps, accs, 83 | svr, mgos_sys_config_get_sw1_in_mode() != (int) InMode::kDetached); 84 | } 85 | } 86 | 87 | } // namespace shelly 88 | -------------------------------------------------------------------------------- /src/ShellyPlug/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "mgos_gpio.h" 19 | 20 | #include "shelly_main.hpp" 21 | #include "shelly_pm_bl0937.hpp" 22 | #include "shelly_sys_led_btn.hpp" 23 | 24 | namespace shelly { 25 | 26 | void CreatePeripherals(std::vector> *inputs, 27 | std::vector> *outputs, 28 | std::vector> *pms UNUSED_ARG, 29 | std::unique_ptr *sys_temp UNUSED_ARG) { 30 | outputs->emplace_back(new OutputPin(1, 4, 1)); 31 | mgos_gpio_setup_output(14, 0); // Red 32 | mgos_gpio_setup_output(16, 0); // Blue 33 | std::unique_ptr pm( 34 | new BL0937PowerMeter(1, 5 /* CF */, -1 /* CF1 */, -1 /* SEL */, 3, 35 | mgos_sys_config_get_bl0937_power_coeff())); 36 | const Status &st = pm->Init(); 37 | if (st.ok()) { 38 | pms->emplace_back(std::move(pm)); 39 | } else { 40 | const std::string &s = st.ToString(); 41 | LOG(LL_ERROR, ("PM init failed: %s", s.c_str())); 42 | } 43 | 44 | InitSysLED(LED_GPIO, LED_ON); 45 | InitSysBtn(BTN_GPIO, BTN_DOWN); 46 | } 47 | 48 | void CreateComponents(std::vector> *comps, 49 | std::vector> *accs, 50 | HAPAccessoryServerRef *svr) { 51 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), nullptr, comps, accs, svr, 52 | true /* to_pri_acc */); 53 | } 54 | 55 | } // namespace shelly 56 | -------------------------------------------------------------------------------- /src/ShellyPlugS/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_main.hpp" 19 | #include "shelly_output.hpp" 20 | #include "shelly_pm_bl0937.hpp" 21 | #include "shelly_sys_led_btn.hpp" 22 | #include "shelly_temp_sensor_ntc.hpp" 23 | 24 | namespace shelly { 25 | 26 | static OutputPin *s_led_out = nullptr; 27 | 28 | void CreatePeripherals(std::vector> *inputs, 29 | std::vector> *outputs, 30 | std::vector> *pms, 31 | std::unique_ptr *sys_temp) { 32 | outputs->emplace_back(new OutputPin(1, 15, 1)); 33 | s_led_out = new OutputPin(99, 0, 0); // Red LED. 34 | std::unique_ptr pm( 35 | new BL0937PowerMeter(1, 5 /* CF */, 14 /* CF1 */, 12 /* SEL */, 2, 36 | mgos_sys_config_get_bl0937_power_coeff())); 37 | const Status &st = pm->Init(); 38 | if (st.ok()) { 39 | pms->emplace_back(std::move(pm)); 40 | } else { 41 | const std::string &s = st.ToString(); 42 | LOG(LL_ERROR, ("PM init failed: %s", s.c_str())); 43 | } 44 | sys_temp->reset(new TempSensorSDNT1608X103F3950(0, 3.3f, 33000.0f)); 45 | 46 | InitSysLED(LED_GPIO, LED_ON); 47 | InitSysBtn(BTN_GPIO, BTN_DOWN); 48 | } 49 | 50 | void CreateComponents(std::vector> *comps, 51 | std::vector> *accs, 52 | HAPAccessoryServerRef *svr) { 53 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), nullptr, comps, accs, svr, 54 | true /* to_pri_acc */, s_led_out); 55 | } 56 | 57 | } // namespace shelly 58 | -------------------------------------------------------------------------------- /src/ShellyPlus1/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_dht_sensor.hpp" 19 | #include "shelly_hap_garage_door_opener.hpp" 20 | #include "shelly_hap_input.hpp" 21 | #include "shelly_input_pin.hpp" 22 | #include "shelly_main.hpp" 23 | #include "shelly_sys_led_btn.hpp" 24 | #include "shelly_temp_sensor_ntc.hpp" 25 | #include "shelly_temp_sensor_ow.hpp" 26 | 27 | namespace shelly { 28 | 29 | static std::unique_ptr s_onewire; 30 | static std::vector> sensors; 31 | 32 | void CreatePeripherals(std::vector> *inputs, 33 | std::vector> *outputs, 34 | std::vector> *pms UNUSED_ARG, 35 | std::unique_ptr *sys_temp) { 36 | outputs->emplace_back(new OutputPin(1, RELAY1_GPIO, 1)); 37 | auto *in = new InputPin(1, SWITCH1_GPIO, 1, MGOS_GPIO_PULL_NONE, true); 38 | in->AddHandler(std::bind(&HandleInputResetSequence, in, LED_GPIO, _1, _2)); 39 | in->Init(); 40 | inputs->emplace_back(in); 41 | sys_temp->reset(new TempSensorSDNT1608X103F3950(ADC_GPIO, 3.3f, 10000.0f)); 42 | 43 | int pin_out = ADDON_OUT_GPIO; 44 | int pin_in = ADDON_IN_GPIO; 45 | 46 | if (DetectAddon(pin_in, pin_out)) { 47 | s_onewire.reset(new Onewire(pin_in, pin_out)); 48 | sensors = s_onewire->DiscoverAll(); 49 | if (sensors.empty()) { 50 | s_onewire.reset(); 51 | sensors = DiscoverDHTSensors(pin_in, pin_out); 52 | } 53 | 54 | if (ADDON_DIG_GPIO != -1) { 55 | auto *in2 = 56 | new InputPin(2, ADDON_DIG_GPIO, 0, MGOS_GPIO_PULL_NONE, false); 57 | in2->Init(); 58 | inputs->emplace_back(in2); 59 | } 60 | 61 | } else { 62 | RestoreUART(); 63 | InitSysLED(LED_GPIO, LED_ON); 64 | } 65 | InitSysBtn(BTN_GPIO, BTN_DOWN); 66 | } 67 | 68 | void CreateComponents(std::vector> *comps, 69 | std::vector> *accs, 70 | HAPAccessoryServerRef *svr) { 71 | bool gdo_mode = mgos_sys_config_get_shelly_mode() == (int) Mode::kGarageDoor; 72 | bool ext_sensor_switch = (FindInput(2) != nullptr); 73 | bool addon_input = !gdo_mode && ext_sensor_switch; 74 | bool single_accessory = 75 | sensors.empty() && !addon_input && 76 | (mgos_sys_config_get_sw1_in_mode() != (int) InMode::kDetached); 77 | if (gdo_mode) { 78 | hap::CreateHAPGDO(1, FindInput(1), FindInput(2), FindOutput(1), 79 | FindOutput(1), mgos_sys_config_get_gdo1(), comps, accs, 80 | svr, true); 81 | } else { 82 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 83 | comps, accs, svr, single_accessory); 84 | } 85 | 86 | if (!sensors.empty()) { 87 | CreateHAPSensors(&sensors, comps, accs, svr); 88 | } 89 | if (addon_input) { 90 | hap::CreateHAPInput(2, mgos_sys_config_get_in2(), comps, accs, svr); 91 | } 92 | } 93 | 94 | } // namespace shelly 95 | -------------------------------------------------------------------------------- /src/ShellyPlusI4/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_dht_sensor.hpp" 19 | #include "shelly_hap_input.hpp" 20 | #include "shelly_hap_stateless_switch.hpp" 21 | #include "shelly_main.hpp" 22 | #include "shelly_noisy_input_pin.hpp" 23 | #include "shelly_sys_led_btn.hpp" 24 | #include "shelly_temp_sensor_ntc.hpp" 25 | #include "shelly_temp_sensor_ow.hpp" 26 | 27 | namespace shelly { 28 | 29 | static std::unique_ptr s_onewire; 30 | static std::vector> sensors; 31 | 32 | void CreatePeripherals(std::vector> *inputs, 33 | std::vector> *outputs UNUSED_ARG, 34 | std::vector> *pms UNUSED_ARG, 35 | std::unique_ptr *sys_temp) { 36 | auto *in1 = new InputPin(1, SWITCH1_GPIO, 1, MGOS_GPIO_PULL_NONE, true); 37 | in1->AddHandler(std::bind(&HandleInputResetSequence, in1, LED_GPIO, _1, _2)); 38 | in1->Init(); 39 | inputs->emplace_back(in1); 40 | 41 | auto *in2 = new NoisyInputPin(2, SWITCH2_GPIO, 1, MGOS_GPIO_PULL_NONE, false); 42 | in2->Init(); 43 | inputs->emplace_back(in2); 44 | 45 | auto *in3 = new NoisyInputPin(3, SWITCH3_GPIO, 1, MGOS_GPIO_PULL_NONE, false); 46 | in3->Init(); 47 | inputs->emplace_back(in3); 48 | 49 | auto *in4 = new NoisyInputPin(4, SWITCH4_GPIO, 1, MGOS_GPIO_PULL_NONE, false); 50 | in4->Init(); 51 | inputs->emplace_back(in4); 52 | 53 | sys_temp->reset(new TempSensorSDNT1608X103F3950(ADC_GPIO, 3.3f, 10000.0f)); 54 | 55 | int pin_out = ADDON_OUT_GPIO; 56 | int pin_in = ADDON_IN_GPIO; 57 | 58 | if (DetectAddon(pin_in, pin_out)) { 59 | s_onewire.reset(new Onewire(pin_in, pin_out)); 60 | sensors = s_onewire->DiscoverAll(); 61 | if (sensors.empty()) { 62 | s_onewire.reset(); 63 | sensors = DiscoverDHTSensors(pin_in, pin_out); 64 | } 65 | } else { 66 | RestoreUART(); 67 | InitSysLED(LED_GPIO, LED_ON); 68 | } 69 | InitSysBtn(BTN_GPIO, BTN_DOWN); 70 | } 71 | 72 | void CreateComponents(std::vector> *comps, 73 | std::vector> *accs, 74 | HAPAccessoryServerRef *svr) { 75 | hap::CreateHAPInput(1, mgos_sys_config_get_in1(), comps, accs, svr); 76 | hap::CreateHAPInput(2, mgos_sys_config_get_in2(), comps, accs, svr); 77 | hap::CreateHAPInput(3, mgos_sys_config_get_in3(), comps, accs, svr); 78 | hap::CreateHAPInput(4, mgos_sys_config_get_in4(), comps, accs, svr); 79 | 80 | if (!sensors.empty()) { 81 | CreateHAPSensors(&sensors, comps, accs, svr); 82 | } 83 | } 84 | 85 | } // namespace shelly 86 | -------------------------------------------------------------------------------- /src/ShellyPlusPlugS/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "mgos_gpio.h" 19 | #include "shelly_main.hpp" 20 | #include "shelly_output.hpp" 21 | #include "shelly_statusled.hpp" 22 | #include "shelly_sys_led_btn.hpp" 23 | #include "shelly_temp_sensor_ntc.hpp" 24 | 25 | #ifdef UART_TX_GPIO 26 | #include "shelly_pm_bl0942.hpp" 27 | #else 28 | #include "shelly_pm_bl0937.hpp" 29 | #endif 30 | 31 | namespace shelly { 32 | 33 | void CreatePeripherals(std::vector> *inputs, 34 | std::vector> *outputs, 35 | std::vector> *pms, 36 | std::unique_ptr *sys_temp) { 37 | outputs->emplace_back(new OutputPin(1, RELAY_GPIO, 1)); 38 | 39 | outputs->emplace_back(new StatusLED(2, NEOPX_GPIO, 2, MGOS_NEOPIXEL_ORDER_GRB, 40 | nullptr, mgos_sys_config_get_led())); 41 | #ifdef NEOPX1_GPIO 42 | outputs->emplace_back(new StatusLED(3, NEOPX1_GPIO, 2, 43 | MGOS_NEOPIXEL_ORDER_GRB, FindOutput(2), 44 | mgos_sys_config_get_led())); 45 | #endif 46 | 47 | #ifndef UART_TX_GPIO 48 | std::unique_ptr pm( 49 | new BL0937PowerMeter(1, 10 /* CF */, 22 /* CF1 */, 19 /* SEL */, 2, 50 | mgos_sys_config_get_bl0937_power_coeff())); 51 | #else 52 | 53 | struct bl0942_cfg cfg = { 54 | .voltage_scale = (73989 / (1.218 * 4)), 55 | .current_scale = (305978 / (1.218)), 56 | .apower_scale = (3537 / (1.218 * 1.218 * 4)), 57 | .aenergy_scale = ((3537 / (1.218 * 1.218 * 4)) * 3600 / (1638.4 * 256))}; 58 | 59 | mgos_config_factory *c = &(mgos_sys_config.factory); 60 | if (c->calib.done) { 61 | mgos_config_scales *g = &c->calib.scales0; 62 | cfg.voltage_scale = g->voltage_scale / 500; 63 | cfg.current_scale = g->current_scale / 2; 64 | cfg.apower_scale = 1e11 / g->apower_scale; 65 | cfg.aenergy_scale = 1e11 / g->aenergy_scale; 66 | } 67 | 68 | std::unique_ptr pm( 69 | new BL0942PowerMeter(1, UART_TX_GPIO, UART_RX_GPIO, 1, 1, cfg)); 70 | #endif 71 | 72 | const Status &st = pm->Init(); 73 | if (st.ok()) { 74 | pms->emplace_back(std::move(pm)); 75 | } else { 76 | const std::string &s = st.ToString(); 77 | LOG(LL_ERROR, ("PM init failed: %s", s.c_str())); 78 | } 79 | sys_temp->reset(new TempSensorSDNT1608X103F3950(ADC_GPIO, 3.3f, 10000.0f)); 80 | 81 | InitSysLED(LED_GPIO, LED_ON); 82 | InitSysBtn(BTN_GPIO, BTN_DOWN); 83 | } 84 | 85 | void CreateComponents(std::vector> *comps, 86 | std::vector> *accs, 87 | HAPAccessoryServerRef *svr) { 88 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), nullptr, comps, accs, svr, 89 | true /* to_pri_acc */, FindOutput(3)); 90 | } 91 | 92 | } // namespace shelly 93 | -------------------------------------------------------------------------------- /src/ShellyT32/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Deomid "rojer" Ryabkov 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "mgos_hap.hpp" 19 | #include "mgos_sys_config.h" 20 | 21 | #include "shelly_input_pin.hpp" 22 | #include "shelly_main.hpp" 23 | #include "shelly_pm.hpp" 24 | #include "shelly_sys_led_btn.hpp" 25 | 26 | namespace shelly { 27 | 28 | void CreatePeripherals(std::vector> *inputs, 29 | std::vector> *outputs, 30 | std::vector> *pms, 31 | std::unique_ptr *sys_temp UNUSED_ARG) { 32 | outputs->emplace_back(new OutputPin(1, 32, 1)); 33 | auto *in = new InputPin(1, 34, 0, MGOS_GPIO_PULL_UP, true); 34 | in->AddHandler(std::bind(&HandleInputResetSequence, in, 32, _1, _2)); 35 | in->Init(); 36 | inputs->emplace_back(in); 37 | 38 | InitSysLED(LED_GPIO, LED_ON); 39 | InitSysBtn(BTN_GPIO, BTN_DOWN); 40 | } 41 | 42 | void CreateComponents(std::vector> *comps, 43 | std::vector> *accs, 44 | HAPAccessoryServerRef *svr) { 45 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 46 | comps, accs, svr, true /* to_pri_acc */); 47 | } 48 | 49 | } // namespace shelly 50 | -------------------------------------------------------------------------------- /src/ShellyU/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | 20 | #include "mgos_hap.h" 21 | #include "mgos_rpc.h" 22 | #include "mgos_sys_config.h" 23 | 24 | #include "shelly_hap_input.hpp" 25 | #include "shelly_hap_temperature_sensor.hpp" 26 | #include "shelly_input_pin.hpp" 27 | #include "shelly_main.hpp" 28 | #include "shelly_mock.hpp" 29 | #include "shelly_output.hpp" 30 | 31 | namespace shelly { 32 | 33 | static std::vector> sensors; 34 | 35 | void CreatePeripherals(std::vector> *inputs, 36 | std::vector> *outputs, 37 | std::vector> *pms, 38 | std::unique_ptr *sys_temp) { 39 | auto *in1 = new InputPin(1, 12, 1, MGOS_GPIO_PULL_NONE, true); 40 | in1->Init(); 41 | inputs->emplace_back(in1); 42 | 43 | auto *in2 = new InputPin(2, 3, 0, MGOS_GPIO_PULL_NONE, false); 44 | in2->Init(); 45 | inputs->emplace_back(in2); 46 | 47 | outputs->emplace_back(new OutputPin(1, 34, 1)); 48 | 49 | g_mock_sys_temp_sensor = new MockTempSensor(33); 50 | sys_temp->reset(g_mock_sys_temp_sensor); 51 | 52 | MockRPCInit(); 53 | (void) pms; 54 | } 55 | 56 | void CreateComponents(std::vector> *comps, 57 | std::vector> *accs, 58 | HAPAccessoryServerRef *svr) { 59 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 60 | comps, accs, svr, false /* to_pri_acc */, 61 | nullptr /* led_out */); 62 | 63 | for (int i = 0; i < 2; i++) { 64 | std::unique_ptr temp(new MockTempSensor(25.125 + i)); 65 | sensors.push_back(std::move(temp)); 66 | } 67 | 68 | bool ext_switch_detected = false; // can be set for testing purposes 69 | 70 | if (ext_switch_detected) { 71 | hap::CreateHAPInput(2, mgos_sys_config_get_in2(), comps, accs, svr); 72 | } else { 73 | if (!sensors.empty()) { 74 | CreateHAPSensors(&sensors, comps, accs, svr); 75 | } 76 | } 77 | } 78 | 79 | } // namespace shelly 80 | -------------------------------------------------------------------------------- /src/ShellyU25/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | 20 | #include "mgos_sys_config.h" 21 | 22 | #include "shelly_input_pin.hpp" 23 | #include "shelly_main.hpp" 24 | #include "shelly_mock.hpp" 25 | #include "shelly_output.hpp" 26 | 27 | namespace shelly { 28 | 29 | void CreatePeripherals(std::vector> *inputs, 30 | std::vector> *outputs, 31 | std::vector> *pms, 32 | std::unique_ptr *sys_temp) { 33 | std::unique_ptr in1(new InputPin(1, 12, 1, MGOS_GPIO_PULL_NONE, true)); 34 | in1->Init(); 35 | inputs->emplace_back(std::move(in1)); 36 | std::unique_ptr in2(new InputPin(2, 13, 1, MGOS_GPIO_PULL_NONE, true)); 37 | in2->Init(); 38 | inputs->emplace_back(std::move(in2)); 39 | 40 | outputs->emplace_back(new OutputPin(1, 34, 1)); 41 | outputs->emplace_back(new OutputPin(2, 35, 1)); 42 | 43 | std::unique_ptr pm1(new MockPowerMeter(1)); 44 | pm1->Init(); 45 | g_mock_pms.push_back(pm1.get()); 46 | pms->emplace_back(std::move(pm1)); 47 | std::unique_ptr pm2(new MockPowerMeter(2)); 48 | pm2->Init(); 49 | g_mock_pms.push_back(pm2.get()); 50 | pms->emplace_back(std::move(pm2)); 51 | 52 | g_mock_sys_temp_sensor = new MockTempSensor(33); 53 | sys_temp->reset(g_mock_sys_temp_sensor); 54 | 55 | MockRPCInit(); 56 | } 57 | 58 | } // namespace shelly 59 | -------------------------------------------------------------------------------- /src/ShellyUNI/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | 20 | #include "shelly_dht_sensor.hpp" 21 | #include "shelly_hap_garage_door_opener.hpp" 22 | #include "shelly_hap_input.hpp" 23 | #include "shelly_hap_window_covering.hpp" 24 | #include "shelly_main.hpp" 25 | #include "shelly_noisy_input_pin.hpp" 26 | #include "shelly_sys_led_btn.hpp" 27 | #include "shelly_temp_sensor_ow.hpp" 28 | 29 | namespace shelly { 30 | 31 | static std::unique_ptr s_onewire; 32 | static std::vector> sensors; 33 | 34 | void CreatePeripherals(std::vector> *inputs, 35 | std::vector> *outputs, 36 | std::vector> *pms, 37 | std::unique_ptr *sys_temp) { 38 | outputs->emplace_back(new OutputPin(1, RELAY1_GPIO, 1)); 39 | outputs->emplace_back(new OutputPin(2, RELAY2_GPIO, 1)); 40 | auto *in1 = new NoisyInputPin(1, SWITCH1_GPIO, 1, MGOS_GPIO_PULL_NONE, true); 41 | in1->AddHandler(std::bind(&HandleInputResetSequence, in1, LED_GPIO, _1, _2)); 42 | in1->Init(); 43 | inputs->emplace_back(in1); 44 | auto *in2 = new NoisyInputPin(2, SWITCH2_GPIO, 1, MGOS_GPIO_PULL_NONE, false); 45 | in2->Init(); 46 | inputs->emplace_back(in2); 47 | 48 | s_onewire.reset(new Onewire(SENSOR_GPIO, SENSOR_GPIO)); 49 | sensors = s_onewire->DiscoverAll(); 50 | if (sensors.empty()) { 51 | s_onewire.reset(); 52 | sensors = DiscoverDHTSensors(SENSOR_GPIO, SENSOR_GPIO); 53 | } 54 | 55 | InitSysLED(LED_GPIO, LED_ON); 56 | InitSysBtn(BTN_GPIO, BTN_DOWN); 57 | } 58 | 59 | void CreateComponents(std::vector> *comps, 60 | std::vector> *accs, 61 | HAPAccessoryServerRef *svr) { 62 | bool gdo_mode = mgos_sys_config_get_shelly_mode() == (int) Mode::kGarageDoor; 63 | 64 | if (gdo_mode) { 65 | hap::CreateHAPGDO(1, FindInput(1), FindInput(2), FindOutput(1), 66 | FindOutput(2), mgos_sys_config_get_gdo1(), comps, accs, 67 | svr, true); 68 | } else { 69 | CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(), 70 | comps, accs, svr, false /* to_pri_acc */); 71 | CreateHAPSwitch(2, mgos_sys_config_get_sw2(), mgos_sys_config_get_in2(), 72 | comps, accs, svr, false /* to_pri_acc */); 73 | } 74 | 75 | if (!sensors.empty()) { 76 | CreateHAPSensors(&sensors, comps, accs, svr); 77 | } 78 | } 79 | 80 | } // namespace shelly 81 | -------------------------------------------------------------------------------- /src/ShellyVintage/shelly_init.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_input.hpp" 19 | #include "shelly_hap_light_bulb.hpp" 20 | #include "shelly_input_pin.hpp" 21 | #include "shelly_light_bulb_controller.hpp" 22 | #include "shelly_main.hpp" 23 | #include "shelly_white_controller.hpp" 24 | 25 | namespace shelly { 26 | 27 | void CreatePeripherals(UNUSED_ARG std::vector> *inputs, 28 | std::vector> *outputs, 29 | UNUSED_ARG std::vector> *pms, 30 | UNUSED_ARG std::unique_ptr *sys_temp) { 31 | outputs->emplace_back(new OutputPin(1, 4, 1)); 32 | } 33 | 34 | void CreateComponents(std::vector> *comps, 35 | std::vector> *accs, 36 | HAPAccessoryServerRef *svr) { 37 | std::unique_ptr lightbulb_controller; 38 | std::unique_ptr hap_light; 39 | auto *lb_cfg = (struct mgos_config_lb *) mgos_sys_config_get_lb1(); 40 | 41 | lightbulb_controller.reset(new WhiteController(lb_cfg, FindOutput(1))); 42 | 43 | hap_light.reset(new hap::LightBulb( 44 | 1, nullptr, std::move(lightbulb_controller), lb_cfg, false)); 45 | 46 | if (hap_light == nullptr || !hap_light->Init().ok()) { 47 | return; 48 | } 49 | 50 | mgos::hap::Accessory *pri_acc = accs->front().get(); 51 | shelly::hap::LightBulb *light_ref = hap_light.get(); 52 | hap_light->set_primary(true); 53 | pri_acc->SetCategory(kHAPAccessoryCategory_Lighting); 54 | pri_acc->AddService(hap_light.get()); 55 | pri_acc->SetIdentifyCB( 56 | [light_ref](const HAPAccessoryIdentifyRequest *request UNUSED_ARG) { 57 | light_ref->Identify(); 58 | return kHAPError_None; 59 | }); 60 | 61 | comps->push_back(std::move(hap_light)); 62 | } 63 | 64 | } // namespace shelly 65 | -------------------------------------------------------------------------------- /src/mock/pwm/mgos_pwm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // TODO: move over to https://github.com/mongoose-os-libs/pwm 19 | 20 | #include "mgos_pwm.h" 21 | 22 | bool mgos_pwm_set(int pin, int freq, float duty) { 23 | return true; 24 | (void) pin; 25 | (void) freq; 26 | (void) duty; 27 | }; 28 | -------------------------------------------------------------------------------- /src/mock/pwm/mgos_pwm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2018 Cesanta Software Limited 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the ""License""); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an ""AS IS"" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #ifndef CS_MOS_LIBS_PWM_SRC_MGOS_PWM_H_ 19 | #define CS_MOS_LIBS_PWM_SRC_MGOS_PWM_H_ 20 | 21 | #include 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* __cplusplus */ 26 | 27 | /* 28 | * 29 | * Set and control the PWM. 30 | * 31 | * Params: 32 | * pin: GPIO number. 33 | * freq: Frequency, in Hz. 0 disables PWM on the pin. 34 | * duty: Specifies which fraction of the cycle is spent in "1" state: 35 | * 0 is always off, 0.5 is a square wave, 1 is always on. 36 | * Return: 37 | * true - SUCCESS, false - FAIL. 38 | * 39 | * Note: 40 | * On esp32 we use 8 channels and 4 timers. 41 | * Each `mgos_set_pwm` call with new pin number assigns a new channel. 42 | * If we already have timer running at the specified frequency, 43 | * we use it instead of assigning a new one. 44 | */ 45 | bool mgos_pwm_set(int pin, int freq, float duty); 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif /* __cplusplus */ 50 | 51 | #endif /* CS_MOS_LIBS_PWM_SRC_MGOS_PWM_H_ */ 52 | -------------------------------------------------------------------------------- /src/mock/shelly_mock.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "shelly_mock_pm.hpp" 23 | #include "shelly_mock_temp_sensor.hpp" 24 | 25 | namespace shelly { 26 | 27 | extern std::vector g_mock_pms; 28 | extern MockTempSensor *g_mock_sys_temp_sensor; 29 | 30 | void MockRPCInit(); 31 | 32 | } // namespace shelly 33 | -------------------------------------------------------------------------------- /src/mock/shelly_mock_pm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_mock_pm.hpp" 19 | 20 | namespace shelly { 21 | 22 | MockPowerMeter::MockPowerMeter(int id) 23 | : PowerMeter(id), 24 | meas_timer_(std::bind(&MockPowerMeter::MeasureTimerCB, this)) { 25 | } 26 | 27 | MockPowerMeter::~MockPowerMeter() { 28 | } 29 | 30 | Status MockPowerMeter::Init() { 31 | meas_timer_.Reset(1000, MGOS_TIMER_REPEAT); 32 | return Status::OK(); 33 | } 34 | 35 | StatusOr MockPowerMeter::GetPowerW() { 36 | return apa_; 37 | } 38 | 39 | StatusOr MockPowerMeter::GetEnergyWH() { 40 | return aea_; 41 | } 42 | 43 | void MockPowerMeter::SetPowerW(float w) { 44 | LOG(LL_INFO, ("PM %d W %.2f -> %.2f", id(), apa_, w)); 45 | apa_ = w; 46 | } 47 | 48 | void MockPowerMeter::SetEnergyWH(float wh) { 49 | LOG(LL_INFO, ("PM %d WH %.2f -> %.2f", id(), aea_, wh)); 50 | aea_ = wh; 51 | } 52 | 53 | void MockPowerMeter::MeasureTimerCB() { 54 | aea_ += (apa_ / 3600); 55 | } 56 | 57 | } // namespace shelly 58 | -------------------------------------------------------------------------------- /src/mock/shelly_mock_pm.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_pm.hpp" 21 | 22 | #include "mgos_timers.hpp" 23 | 24 | namespace shelly { 25 | 26 | class MockPowerMeter : public PowerMeter { 27 | public: 28 | explicit MockPowerMeter(int id); 29 | virtual ~MockPowerMeter(); 30 | 31 | // PowerMeter interface impl. 32 | Status Init() override; 33 | StatusOr GetPowerW() override; 34 | StatusOr GetEnergyWH() override; 35 | 36 | void SetPowerW(float w); 37 | void SetEnergyWH(float wh); 38 | 39 | private: 40 | void MeasureTimerCB(); 41 | 42 | float apa_ = 0; 43 | float aea_ = 0; 44 | mgos::Timer meas_timer_; 45 | }; 46 | 47 | } // namespace shelly 48 | -------------------------------------------------------------------------------- /src/mock/shelly_mock_rpc_service.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_mock.hpp" 19 | 20 | #include 21 | 22 | #include "mgos_rpc.h" 23 | 24 | #include "shelly_mock_pm.hpp" 25 | #include "shelly_mock_temp_sensor.hpp" 26 | 27 | namespace shelly { 28 | 29 | std::vector g_mock_pms; 30 | MockTempSensor *g_mock_sys_temp_sensor = nullptr; 31 | 32 | static void MockSetSysTempHandler(struct mg_rpc_request_info *ri, void *cb_arg, 33 | struct mg_rpc_frame_info *fi, 34 | struct mg_str args) { 35 | float temp = NAN; 36 | json_scanf(args.p, args.len, ri->args_fmt, &temp); 37 | g_mock_sys_temp_sensor->SetValue(temp); 38 | mg_rpc_send_responsef(ri, nullptr); 39 | (void) fi; 40 | (void) cb_arg; 41 | } 42 | 43 | static void MockSetPM(struct mg_rpc_request_info *ri, void *cb_arg, 44 | struct mg_rpc_frame_info *fi, struct mg_str args) { 45 | int id = -1; 46 | float w = NAN, wh = NAN; 47 | json_scanf(args.p, args.len, ri->args_fmt, &id, &w, &wh); 48 | if (id < 0) { 49 | mg_rpc_send_errorf(ri, 400, "%s is required", "id"); 50 | return; 51 | } 52 | if (std::isnan(w) && std::isnan(wh)) { 53 | mg_rpc_send_errorf(ri, 400, "%s is required", "w or wh"); 54 | return; 55 | } 56 | for (auto *pm : g_mock_pms) { 57 | if (pm->id() == id) { 58 | if (!std::isnan(w)) pm->SetPowerW(w); 59 | if (!std::isnan(wh)) pm->SetEnergyWH(wh); 60 | mg_rpc_send_responsef(ri, nullptr); 61 | return; 62 | } 63 | } 64 | mg_rpc_send_errorf(ri, 404, "pm %d not found", id); 65 | (void) fi; 66 | (void) cb_arg; 67 | } 68 | 69 | void MockRPCInit() { 70 | mg_rpc_add_handler(mgos_rpc_get_global(), "Shelly.Mock.SetSysTemp", 71 | "{temp: %f}", MockSetSysTempHandler, nullptr); 72 | mg_rpc_add_handler(mgos_rpc_get_global(), "Shelly.Mock.SetPM", 73 | "{id: %d, w: %f, wh: %f}", MockSetPM, nullptr); 74 | } 75 | 76 | } // namespace shelly 77 | -------------------------------------------------------------------------------- /src/mock/shelly_mock_temp_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_mock_temp_sensor.hpp" 19 | 20 | #include "shelly_common.hpp" 21 | 22 | #include 23 | 24 | namespace shelly { 25 | 26 | MockTempSensor::MockTempSensor(float initial_value) : value_(initial_value) { 27 | } 28 | 29 | MockTempSensor::~MockTempSensor() { 30 | } 31 | 32 | Status MockTempSensor::Init() { 33 | return Status::OK(); 34 | } 35 | 36 | StatusOr MockTempSensor::GetTemperature() { 37 | if (std::isnan(value_)) { 38 | return mgos::Status(STATUS_UNAVAILABLE, "failed"); 39 | } 40 | return value_; 41 | } 42 | 43 | void MockTempSensor::SetValue(float new_value) { 44 | value_ = new_value; 45 | } 46 | 47 | } // namespace shelly 48 | -------------------------------------------------------------------------------- /src/mock/shelly_mock_temp_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_temp_sensor.hpp" 21 | 22 | namespace shelly { 23 | 24 | class MockTempSensor : public TempSensor { 25 | public: 26 | MockTempSensor(float initial_value); 27 | virtual ~MockTempSensor(); 28 | 29 | Status Init() override; 30 | StatusOr GetTemperature() override; 31 | 32 | void SetValue(float new_value); 33 | 34 | private: 35 | float value_; 36 | }; 37 | 38 | } // namespace shelly 39 | -------------------------------------------------------------------------------- /src/mock/wifi_config/shelly_wifi_config_impl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_wifi_config.hpp" 19 | 20 | #include "mgos.hpp" 21 | 22 | namespace shelly { 23 | 24 | static WifiConfig s_cfg; 25 | 26 | WifiConfig GetWifiConfig() { 27 | return s_cfg; 28 | } 29 | 30 | Status SetWifiConfig(const WifiConfig &cfg) { 31 | std::string cs = cfg.ToJSON(); 32 | LOG(LL_INFO, ("Set wifi config to: %s", cs.c_str())); 33 | s_cfg = cfg; 34 | return Status::OK(); 35 | } 36 | 37 | void ResetWifiConfig() { 38 | s_cfg = WifiConfig(); 39 | } 40 | 41 | WifiInfo GetWifiInfo() { 42 | WifiInfo empty; 43 | return empty; 44 | } 45 | 46 | void ReportClientRequest(const std::string &client_addr) { 47 | (void) client_addr; 48 | } 49 | 50 | void InitWifiConfigManager() { 51 | } 52 | 53 | void StartWifiConfigManager() { 54 | } 55 | 56 | std::string GetMACAddr(bool sta UNUSED_ARG, bool delims) { 57 | uint8_t mac[6]; 58 | device_get_mac_address(mac); 59 | return FormatMACAddr(mac, delims); 60 | } 61 | 62 | } // namespace shelly 63 | -------------------------------------------------------------------------------- /src/shelly_cct_controller.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_cct_controller.hpp" 19 | 20 | #include "mgos.hpp" 21 | #include "mgos_hap_chars.hpp" 22 | 23 | namespace shelly { 24 | 25 | CCTController::CCTController(struct mgos_config_lb *cfg, Output *out_cw, 26 | Output *out_ww) 27 | : LightBulbController(cfg), out_ww_(out_ww), out_cw_(out_cw) { 28 | } 29 | 30 | CCTController::~CCTController() { 31 | } 32 | 33 | void CCTController::ReportTransition(const StateCCT &next, 34 | const StateCCT &prev) { 35 | LOG(LL_INFO, ("Output 1: %.2f => %.2f", prev.ww, next.ww)); 36 | LOG(LL_INFO, ("Output 2: %.2f => %.2f", prev.cw, next.cw)); 37 | } 38 | 39 | void CCTController::UpdatePWM(const StateCCT &state) { 40 | out_ww_->SetStatePWM(state.ww, "transition"); 41 | out_cw_->SetStatePWM(state.cw, "transition"); 42 | } 43 | 44 | StateCCT CCTController::ConfigToState(const struct mgos_config_lb &cfg) const { 45 | StateCCT state{}; 46 | 47 | if (!cfg.state) return state; 48 | 49 | float v = cfg.brightness / 100.0f; 50 | float temp = cfg.color_temperature; 51 | 52 | // brightness and color temperature [mired] to cw, ww values 53 | // uses additive mixing, so at middle temp it is 50/50 54 | int temp_max = 400; 55 | int temp_min = 50; 56 | temp -= temp_min; 57 | temp /= (temp_max - temp_min); 58 | state.ww = temp * v; 59 | state.cw = (1.0f - temp) * v; 60 | return state; 61 | } 62 | 63 | std::string StateCCT::ToString() const { 64 | return mgos::SPrintf("[ww=%.2f cw=%.2f]", ww, cw); 65 | } 66 | 67 | } // namespace shelly 68 | -------------------------------------------------------------------------------- /src/shelly_cct_controller.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "mgos.hpp" 21 | #include "mgos_hap_chars.hpp" 22 | #include "mgos_timers.hpp" 23 | #include "shelly_light_bulb_controller.hpp" 24 | #include "shelly_output.hpp" 25 | 26 | namespace shelly { 27 | 28 | struct StateCCT { 29 | float ww; 30 | float cw; 31 | 32 | StateCCT operator+(const StateCCT &other) const { 33 | return { 34 | .ww = ww + other.ww, 35 | .cw = cw + other.cw, 36 | }; 37 | } 38 | 39 | StateCCT operator*(float a) const { 40 | return { 41 | .ww = a * ww, 42 | .cw = a * cw, 43 | }; 44 | } 45 | 46 | std::string ToString() const; 47 | }; 48 | 49 | class CCTController : public LightBulbController { 50 | public: 51 | CCTController(struct mgos_config_lb *cfg, Output *out_ww, Output *out_cw); 52 | CCTController(const CCTController &other) = delete; 53 | ~CCTController(); 54 | 55 | BulbType Type() final { 56 | return BulbType::kCCT; 57 | } 58 | 59 | private: 60 | Output *const out_ww_, *const out_cw_; 61 | 62 | StateCCT ConfigToState(const struct mgos_config_lb &cfg) const final; 63 | void ReportTransition(const StateCCT &next, const StateCCT &prev) final; 64 | void UpdatePWM(const StateCCT &state) final; 65 | }; 66 | } // namespace shelly 67 | -------------------------------------------------------------------------------- /src/shelly_component.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_component.hpp" 19 | 20 | namespace shelly { 21 | 22 | Component::Component(int id) : id_(id) { 23 | } 24 | 25 | Component::~Component() { 26 | } 27 | 28 | int Component::id() const { 29 | return id_; 30 | } 31 | 32 | void Component::Identify() { 33 | LOG(LL_INFO, ("== Identify %d %d %s", id(), (int) type(), name().c_str())); 34 | } 35 | 36 | bool Component::IsIdle() { 37 | return true; 38 | } 39 | 40 | } // namespace shelly 41 | -------------------------------------------------------------------------------- /src/shelly_component.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_common.hpp" 21 | 22 | namespace shelly { 23 | 24 | class Component { 25 | public: 26 | // NB: Keep in sync with Component_Type in JS. 27 | enum class Type { 28 | kSwitch = 0, 29 | kOutlet = 1, 30 | kLock = 2, 31 | kStatelessSwitch = 3, 32 | kWindowCovering = 4, 33 | kGarageDoorOpener = 5, 34 | kDisabledInput = 6, 35 | kMotionSensor = 7, 36 | kOccupancySensor = 8, 37 | kContactSensor = 9, 38 | kDoorbell = 10, 39 | kLightBulb = 11, 40 | kTemperatureSensor = 12, 41 | kLeakSensor = 13, 42 | kSmokeSensor = 14, 43 | kCarbonMonoxideSensor = 15, 44 | kCarbonDioxideSensor = 16, 45 | kMax, 46 | }; 47 | 48 | explicit Component(int id); 49 | virtual ~Component(); 50 | 51 | int id() const; 52 | 53 | // Complex initialization after construction. 54 | virtual Status Init() = 0; 55 | virtual Type type() const = 0; 56 | virtual std::string name() const = 0; 57 | 58 | // Short status snippet string. 59 | virtual StatusOr GetInfo() const = 0; 60 | // Full JSON status for UI. 61 | virtual StatusOr GetInfoJSON() const = 0; 62 | // Set configuration from UI. 63 | virtual Status SetConfig(const std::string &config_json, 64 | bool *restart_required) = 0; 65 | // Set state from UI. 66 | virtual Status SetState(const std::string &state_json) = 0; 67 | // Do something to identify this component to the user. 68 | // Default is to print a log message, which is to say - not much. 69 | virtual void Identify(); 70 | 71 | // Is there any activity going on? 72 | // If true is returned, it means it's ok to destroy the component. 73 | // False should be returned if there is any user-visible activity, 74 | // like curtain moving. 75 | // Default implementation always returns true. 76 | virtual bool IsIdle(); 77 | 78 | private: 79 | const int id_; 80 | 81 | Component(const Component &other) = delete; 82 | }; 83 | 84 | } // namespace shelly 85 | -------------------------------------------------------------------------------- /src/shelly_debug.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | 20 | #include "HAP.h" 21 | 22 | namespace shelly { 23 | 24 | void GetDebugInfo(std::string *out); 25 | 26 | void SetDebugEnable(bool debug_en); 27 | 28 | bool DebugInit(HAPAccessoryServerRef *svr, HAPPlatformKeyValueStoreRef kvs, 29 | HAPPlatformTCPStreamManagerRef tcpm); 30 | 31 | } // namespace shelly 32 | -------------------------------------------------------------------------------- /src/shelly_hap_carbon_dioxide_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_carbon_dioxide_sensor.hpp" 19 | 20 | namespace shelly { 21 | namespace hap { 22 | 23 | CarbonDioxideSensor::CarbonDioxideSensor(int id, Input *in, 24 | struct mgos_config_in_sensor *cfg) 25 | : SensorBase(id, in, cfg, SHELLY_HAP_IID_BASE_CARBON_DIOXIDE_SENSOR, 26 | &kHAPServiceType_CarbonDioxideSensor, 27 | kHAPServiceDebugDescription_CarbonDioxideSensor) { 28 | } 29 | 30 | CarbonDioxideSensor::~CarbonDioxideSensor() { 31 | } 32 | 33 | Component::Type CarbonDioxideSensor::type() const { 34 | return Type::kCarbonDioxideSensor; 35 | } 36 | 37 | Status CarbonDioxideSensor::Init() { 38 | const Status &st = SensorBase::Init(); 39 | if (!st.ok()) return st; 40 | AddChar(new mgos::hap::UInt8Characteristic( 41 | svc_.iid + 2, &kHAPCharacteristicType_CarbonDioxideDetected, 0, 1, 1, 42 | std::bind(&mgos::hap::ReadUInt8, _1, _2, _3, &state_), 43 | true /* supports_notification */, nullptr /* write_handler */, 44 | kHAPCharacteristicDebugDescription_CarbonDioxideDetected)); 45 | return Status::OK(); 46 | } 47 | 48 | } // namespace hap 49 | } // namespace shelly 50 | -------------------------------------------------------------------------------- /src/shelly_hap_carbon_dioxide_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_hap_sensor_base.hpp" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | class CarbonDioxideSensor : public SensorBase { 26 | public: 27 | CarbonDioxideSensor(int id, Input *in, struct mgos_config_in_sensor *cfg); 28 | virtual ~CarbonDioxideSensor(); 29 | 30 | // Component interface impl. 31 | Status Init() override; 32 | virtual Type type() const override; 33 | }; 34 | 35 | } // namespace hap 36 | } // namespace shelly 37 | -------------------------------------------------------------------------------- /src/shelly_hap_carbon_monoxide_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_carbon_monoxide_sensor.hpp" 19 | 20 | namespace shelly { 21 | namespace hap { 22 | 23 | CarbonMonoxideSensor::CarbonMonoxideSensor(int id, Input *in, 24 | struct mgos_config_in_sensor *cfg) 25 | : SensorBase(id, in, cfg, SHELLY_HAP_IID_BASE_CARBON_MONOXIDE_SENSOR, 26 | &kHAPServiceType_CarbonMonoxideSensor, 27 | kHAPServiceDebugDescription_CarbonMonoxideSensor) { 28 | } 29 | 30 | CarbonMonoxideSensor::~CarbonMonoxideSensor() { 31 | } 32 | 33 | Component::Type CarbonMonoxideSensor::type() const { 34 | return Type::kCarbonMonoxideSensor; 35 | } 36 | 37 | Status CarbonMonoxideSensor::Init() { 38 | const Status &st = SensorBase::Init(); 39 | if (!st.ok()) return st; 40 | AddChar(new mgos::hap::UInt8Characteristic( 41 | svc_.iid + 2, &kHAPCharacteristicType_CarbonMonoxideDetected, 0, 1, 1, 42 | std::bind(&mgos::hap::ReadUInt8, _1, _2, _3, &state_), 43 | true /* supports_notification */, nullptr /* write_handler */, 44 | kHAPCharacteristicDebugDescription_CarbonMonoxideDetected)); 45 | return Status::OK(); 46 | } 47 | 48 | } // namespace hap 49 | } // namespace shelly 50 | -------------------------------------------------------------------------------- /src/shelly_hap_carbon_monoxide_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_hap_sensor_base.hpp" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | class CarbonMonoxideSensor : public SensorBase { 26 | public: 27 | CarbonMonoxideSensor(int id, Input *in, struct mgos_config_in_sensor *cfg); 28 | virtual ~CarbonMonoxideSensor(); 29 | 30 | // Component interface impl. 31 | Status Init() override; 32 | virtual Type type() const override; 33 | }; 34 | 35 | } // namespace hap 36 | } // namespace shelly 37 | -------------------------------------------------------------------------------- /src/shelly_hap_contact_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_contact_sensor.hpp" 19 | 20 | namespace shelly { 21 | namespace hap { 22 | 23 | ContactSensor::ContactSensor(int id, Input *in, 24 | struct mgos_config_in_sensor *cfg) 25 | : SensorBase(id, in, cfg, SHELLY_HAP_IID_BASE_CONTACT_SENSOR, 26 | &kHAPServiceType_ContactSensor, 27 | kHAPServiceDebugDescription_ContactSensor) { 28 | } 29 | 30 | ContactSensor::~ContactSensor() { 31 | } 32 | 33 | Component::Type ContactSensor::type() const { 34 | return Type::kContactSensor; 35 | } 36 | 37 | Status ContactSensor::Init() { 38 | const Status &st = SensorBase::Init(); 39 | if (!st.ok()) return st; 40 | AddChar(new mgos::hap::UInt8Characteristic( 41 | svc_.iid + 2, &kHAPCharacteristicType_ContactSensorState, 0, 1, 1, 42 | [this](HAPAccessoryServerRef *, const HAPUInt8CharacteristicReadRequest *, 43 | uint8_t *value) { 44 | *value = !state_; 45 | return kHAPError_None; 46 | }, 47 | true /* supports_notification */, nullptr /* write_handler */, 48 | kHAPCharacteristicDebugDescription_ContactSensorState)); 49 | return Status::OK(); 50 | } 51 | 52 | } // namespace hap 53 | } // namespace shelly 54 | -------------------------------------------------------------------------------- /src/shelly_hap_contact_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_hap_sensor_base.hpp" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | class ContactSensor : public SensorBase { 26 | public: 27 | ContactSensor(int id, Input *in, struct mgos_config_in_sensor *cfg); 28 | virtual ~ContactSensor(); 29 | 30 | // Component interface impl. 31 | Status Init() override; 32 | virtual Type type() const override; 33 | }; 34 | 35 | } // namespace hap 36 | } // namespace shelly 37 | -------------------------------------------------------------------------------- /src/shelly_hap_doorbell.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_doorbell.hpp" 19 | 20 | #include "HAPUUID.h" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | const HAPUUID kHAPServiceType_Doorbell = HAPUUIDCreateAppleDefined(0x121); 26 | 27 | Doorbell::Doorbell(int id, Input *in, struct mgos_config_in_ssw *cfg) 28 | : StatelessSwitchBase(id, in, cfg, SHELLY_HAP_IID_BASE_DOORBELL, 29 | &kHAPServiceType_Doorbell, "service.doorbell") { 30 | } 31 | 32 | Doorbell::~Doorbell() { 33 | } 34 | 35 | Component::Type Doorbell::type() const { 36 | return Type::kDoorbell; 37 | } 38 | 39 | } // namespace hap 40 | } // namespace shelly -------------------------------------------------------------------------------- /src/shelly_hap_doorbell.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | #include "shelly_hap_stateless_switch_base.hpp" 20 | 21 | namespace shelly { 22 | namespace hap { 23 | 24 | class Doorbell : public StatelessSwitchBase { 25 | public: 26 | Doorbell(int id, Input *in, struct mgos_config_in_ssw *cfg); 27 | virtual ~Doorbell(); 28 | 29 | // Component interface impl. 30 | Type type() const override; 31 | }; 32 | 33 | } // namespace hap 34 | } // namespace shelly -------------------------------------------------------------------------------- /src/shelly_hap_garage_door_opener.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "mgos_hap_chars.hpp" 24 | #include "mgos_hap_service.hpp" 25 | #include "mgos_sys_config.h" 26 | #include "mgos_timers.hpp" 27 | 28 | #include "shelly_common.hpp" 29 | #include "shelly_component.hpp" 30 | #include "shelly_input.hpp" 31 | #include "shelly_output.hpp" 32 | 33 | namespace shelly { 34 | namespace hap { 35 | 36 | // Common base for Switch, Outlet and Lock services. 37 | class GarageDoorOpener : public Component, public mgos::hap::Service { 38 | public: 39 | GarageDoorOpener(int id, Input *in_close, Input *in_open, Output *out_open, 40 | Output *out_close, struct mgos_config_gdo *cfg); 41 | virtual ~GarageDoorOpener(); 42 | 43 | // Component interface impl. 44 | Type type() const override; 45 | std::string name() const override; 46 | Status Init() override; 47 | StatusOr GetInfo() const override; 48 | StatusOr GetInfoJSON() const override; 49 | Status SetConfig(const std::string &config_json, 50 | bool *restart_required) override; 51 | Status SetState(const std::string &state_json) override; 52 | bool IsIdle() override; 53 | 54 | private: 55 | // NB: Values correspond to HAP Current Door State values. 56 | enum class State { 57 | kOpen = 0, 58 | kClosed = 1, 59 | kOpening = 2, 60 | kClosing = 3, 61 | kStopped = 4, 62 | }; 63 | 64 | static const char *StateStr(State state); 65 | 66 | void GetInputsState(int *is_closed, int *is_open) const; 67 | void SetCurState(State new_state); 68 | void SetTgtState(State new_state, const char *source); 69 | void ToggleState(const char *source); 70 | HAPError HAPTgtStateWrite(HAPAccessoryServerRef *svr, 71 | const HAPUInt8CharacteristicWriteRequest *req, 72 | uint8_t value); 73 | 74 | void RunOnce(); 75 | 76 | Input *in_close_, *in_open_; 77 | Output *out_close_, *out_open_; 78 | struct mgos_config_gdo *cfg_; 79 | 80 | mgos::Timer state_timer_; 81 | 82 | mgos::hap::Characteristic *cur_state_char_ = nullptr; 83 | mgos::hap::Characteristic *tgt_state_char_ = nullptr; 84 | mgos::hap::Characteristic *obst_char_ = nullptr; 85 | 86 | State cur_state_; 87 | State tgt_state_; 88 | State pre_stopped_state_; 89 | int64_t begin_ = 0; 90 | bool obstruction_detected_ = false; 91 | }; 92 | 93 | void CreateHAPGDO(int id, Input *in_close, Input *in_open, Output *out_close, 94 | Output *out_open, const struct mgos_config_gdo *gdo_cfg, 95 | std::vector> *comps, 96 | std::vector> *accs, 97 | HAPAccessoryServerRef *svr, bool to_pri_acc); 98 | 99 | } // namespace hap 100 | } // namespace shelly 101 | -------------------------------------------------------------------------------- /src/shelly_hap_humidity_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "mgos_hap_service.hpp" 21 | #include "mgos_sys_config.h" 22 | 23 | #include "shelly_common.hpp" 24 | #include "shelly_component.hpp" 25 | #include "shelly_temp_sensor.hpp" 26 | 27 | namespace shelly { 28 | namespace hap { 29 | 30 | class HumiditySensor : public Component, public mgos::hap::Service { 31 | public: 32 | HumiditySensor(int id, HumidityTempSensor *sensor, 33 | struct mgos_config_ts *cfg); 34 | virtual ~HumiditySensor(); 35 | 36 | // Component interface impl. 37 | Type type() const override; 38 | std::string name() const override; 39 | Status Init() override; 40 | 41 | StatusOr GetInfo() const override; 42 | StatusOr GetInfoJSON() const override; 43 | Status SetConfig(const std::string &config_json, 44 | bool *restart_required) override; 45 | Status SetState(const std::string &state_json) override; 46 | 47 | private: 48 | HumidityTempSensor *hum_sensor_; 49 | struct mgos_config_ts *cfg_; 50 | 51 | mgos::hap::FloatCharacteristic *current_humidity_characteristic_; 52 | 53 | void ValueChanged(); 54 | }; 55 | 56 | void CreateHAPHumiditySensor( 57 | int id, HumidityTempSensor *sensor, const struct mgos_config_ts *ts_cfg, 58 | std::vector> *comps, 59 | std::vector> *accs, 60 | HAPAccessoryServerRef *svr); 61 | 62 | } // namespace hap 63 | } // namespace shelly 64 | -------------------------------------------------------------------------------- /src/shelly_hap_input.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "mgos_hap.hpp" 24 | #include "mgos_sys_config.h" 25 | 26 | #include "shelly_common.hpp" 27 | #include "shelly_component.hpp" 28 | #include "shelly_input.hpp" 29 | 30 | namespace shelly { 31 | namespace hap { 32 | 33 | // A service that represents a single Shelly input. 34 | // Internally it instantiates either a Stateless Switch or Motion Sensor 35 | // and forwards API calls to it. 36 | class ShellyInput : public Component { 37 | public: 38 | ShellyInput(int id, Input *in, struct mgos_config_in *cfg); 39 | virtual ~ShellyInput(); 40 | 41 | // Component interface impl. 42 | Type type() const override; 43 | Status Init() override; 44 | std::string name() const override; 45 | StatusOr GetInfo() const override; 46 | StatusOr GetInfoJSON() const override; 47 | Status SetConfig(const std::string &config_json, 48 | bool *restart_required) override; 49 | Status SetState(const std::string &state_json) override; 50 | 51 | uint16_t GetAIDBase() const; 52 | mgos::hap::Service *GetService() const; 53 | 54 | private: 55 | static bool IsValidType(int type); 56 | 57 | Input *const in_; 58 | struct mgos_config_in *cfg_; 59 | Type initial_type_; // Type at creation. 60 | 61 | std::unique_ptr c_; 62 | mgos::hap::Service *s_ = nullptr; 63 | 64 | ShellyInput(const ShellyInput &other) = delete; 65 | }; 66 | 67 | void CreateHAPInput(int id, const struct mgos_config_in *cfg, 68 | std::vector> *comps, 69 | std::vector> *accs, 70 | HAPAccessoryServerRef *svr); 71 | 72 | } // namespace hap 73 | } // namespace shelly 74 | -------------------------------------------------------------------------------- /src/shelly_hap_leak_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_leak_sensor.hpp" 19 | 20 | namespace shelly { 21 | namespace hap { 22 | 23 | LeakSensor::LeakSensor(int id, Input *in, struct mgos_config_in_sensor *cfg) 24 | : SensorBase(id, in, cfg, SHELLY_HAP_IID_BASE_LEAK_SENSOR, 25 | &kHAPServiceType_LeakSensor, 26 | kHAPServiceDebugDescription_LeakSensor) { 27 | } 28 | 29 | LeakSensor::~LeakSensor() { 30 | } 31 | 32 | Component::Type LeakSensor::type() const { 33 | return Type::kLeakSensor; 34 | } 35 | 36 | Status LeakSensor::Init() { 37 | const Status &st = SensorBase::Init(); 38 | if (!st.ok()) return st; 39 | AddChar(new mgos::hap::UInt8Characteristic( 40 | svc_.iid + 2, &kHAPCharacteristicType_LeakDetected, 0, 1, 1, 41 | std::bind(&mgos::hap::ReadUInt8, _1, _2, _3, &state_), 42 | true /* supports_notification */, nullptr /* write_handler */, 43 | kHAPCharacteristicDebugDescription_LeakDetected)); 44 | return Status::OK(); 45 | } 46 | 47 | } // namespace hap 48 | } // namespace shelly 49 | -------------------------------------------------------------------------------- /src/shelly_hap_leak_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_hap_sensor_base.hpp" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | class LeakSensor : public SensorBase { 26 | public: 27 | LeakSensor(int id, Input *in, struct mgos_config_in_sensor *cfg); 28 | virtual ~LeakSensor(); 29 | 30 | // Component interface impl. 31 | Status Init() override; 32 | virtual Type type() const override; 33 | }; 34 | 35 | } // namespace hap 36 | } // namespace shelly 37 | -------------------------------------------------------------------------------- /src/shelly_hap_lock.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_lock.hpp" 19 | 20 | #include "mgos_hap_accessory.hpp" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | Lock::Lock(int id, Input *in, Output *out, PowerMeter *out_pm, Output *led_out, 26 | struct mgos_config_sw *cfg) 27 | : ShellySwitch(id, in, out, out_pm, led_out, cfg) { 28 | } 29 | 30 | Lock::~Lock() { 31 | } 32 | 33 | Status Lock::Init() { 34 | auto st = ShellySwitch::Init(); 35 | if (!st.ok()) return st; 36 | 37 | const int id1 = id() - 1; // IDs used to start at 0, preserve compat. 38 | uint16_t iid = SHELLY_HAP_IID_BASE_LOCK + (SHELLY_HAP_IID_STEP_LOCK * id1); 39 | svc_.iid = iid++; 40 | svc_.serviceType = &kHAPServiceType_LockMechanism; 41 | svc_.debugDescription = kHAPServiceDebugDescription_LockMechanism; 42 | // Name 43 | AddNameChar(iid++, cfg_->name); 44 | // Current State 45 | auto *cur_state_char = new mgos::hap::UInt8Characteristic( 46 | iid++, &kHAPCharacteristicType_LockCurrentState, 0, 3, 1, 47 | std::bind(&Lock::HandleCurrentStateRead, this, _1, _2, _3), 48 | true /* supports_notification */, nullptr /* write_handler */, 49 | kHAPCharacteristicDebugDescription_LockCurrentState); 50 | state_notify_chars_.push_back(cur_state_char); 51 | AddChar(cur_state_char); 52 | // Target State 53 | auto *tgt_state_char = new mgos::hap::UInt8Characteristic( 54 | iid++, &kHAPCharacteristicType_LockTargetState, 0, 3, 1, 55 | std::bind(&Lock::HandleCurrentStateRead, this, _1, _2, _3), 56 | true /* supports_notification */, 57 | [this](HAPAccessoryServerRef *server UNUSED_ARG, 58 | const HAPUInt8CharacteristicWriteRequest *request UNUSED_ARG, 59 | uint8_t value) { 60 | SetOutputState((value == 0), "HAP"); 61 | state_notify_chars_[1]->RaiseEvent(); 62 | return kHAPError_None; 63 | }, 64 | kHAPCharacteristicDebugDescription_LockTargetState); 65 | state_notify_chars_.push_back(tgt_state_char); 66 | AddChar(tgt_state_char); 67 | 68 | return Status::OK(); 69 | } 70 | 71 | HAPError Lock::HandleCurrentStateRead( 72 | HAPAccessoryServerRef *server, 73 | const HAPUInt8CharacteristicReadRequest *request, uint8_t *value) { 74 | *value = (out_->GetState() ? 0 : 1); 75 | (void) server; 76 | (void) request; 77 | return kHAPError_None; 78 | } 79 | 80 | } // namespace hap 81 | } // namespace shelly 82 | -------------------------------------------------------------------------------- /src/shelly_hap_lock.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "mgos_hap_chars.hpp" 21 | #include "shelly_switch.hpp" 22 | 23 | namespace shelly { 24 | namespace hap { 25 | 26 | class Lock : public ShellySwitch { 27 | public: 28 | Lock(int id, Input *in, Output *out, PowerMeter *out_pm, Output *led_out, 29 | struct mgos_config_sw *cfg); 30 | virtual ~Lock(); 31 | 32 | Status Init(); 33 | 34 | private: 35 | HAPError HandleCurrentStateRead( 36 | HAPAccessoryServerRef *server, 37 | const HAPUInt8CharacteristicReadRequest *request, uint8_t *value); 38 | }; 39 | 40 | } // namespace hap 41 | } // namespace shelly 42 | -------------------------------------------------------------------------------- /src/shelly_hap_motion_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_motion_sensor.hpp" 19 | 20 | namespace shelly { 21 | namespace hap { 22 | 23 | MotionSensor::MotionSensor(int id, Input *in, struct mgos_config_in_sensor *cfg) 24 | : SensorBase(id, in, cfg, SHELLY_HAP_IID_BASE_MOTION_SENSOR, 25 | &kHAPServiceType_MotionSensor, 26 | kHAPServiceDebugDescription_MotionSensor) { 27 | } 28 | 29 | MotionSensor::~MotionSensor() { 30 | } 31 | 32 | Component::Type MotionSensor::type() const { 33 | return Type::kMotionSensor; 34 | } 35 | 36 | Status MotionSensor::Init() { 37 | const Status &st = SensorBase::Init(); 38 | if (!st.ok()) return st; 39 | AddChar(new mgos::hap::BoolCharacteristic( 40 | svc_.iid + 2, &kHAPCharacteristicType_MotionDetected, 41 | std::bind(&mgos::hap::ReadBool, _1, _2, _3, &state_), 42 | true /* supports_notification */, nullptr /* write_handler */, 43 | kHAPCharacteristicDebugDescription_MotionDetected)); 44 | return Status::OK(); 45 | } 46 | 47 | } // namespace hap 48 | } // namespace shelly 49 | -------------------------------------------------------------------------------- /src/shelly_hap_motion_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_hap_sensor_base.hpp" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | class MotionSensor : public SensorBase { 26 | public: 27 | MotionSensor(int id, Input *in, struct mgos_config_in_sensor *cfg); 28 | virtual ~MotionSensor(); 29 | 30 | // Component interface impl. 31 | Status Init() override; 32 | virtual Type type() const override; 33 | }; 34 | 35 | } // namespace hap 36 | } // namespace shelly 37 | -------------------------------------------------------------------------------- /src/shelly_hap_occupancy_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_occupancy_sensor.hpp" 19 | 20 | namespace shelly { 21 | namespace hap { 22 | 23 | OccupancySensor::OccupancySensor(int id, Input *in, 24 | struct mgos_config_in_sensor *cfg) 25 | : SensorBase(id, in, cfg, SHELLY_HAP_IID_BASE_OCCUPANCY_SENSOR, 26 | &kHAPServiceType_OccupancySensor, 27 | kHAPServiceDebugDescription_OccupancySensor) { 28 | } 29 | 30 | OccupancySensor::~OccupancySensor() { 31 | } 32 | 33 | Component::Type OccupancySensor::type() const { 34 | return Type::kOccupancySensor; 35 | } 36 | 37 | Status OccupancySensor::Init() { 38 | const Status &st = SensorBase::Init(); 39 | if (!st.ok()) return st; 40 | AddChar(new mgos::hap::BoolCharacteristic( 41 | svc_.iid + 2, &kHAPCharacteristicType_OccupancyDetected, 42 | std::bind(&mgos::hap::ReadBool, _1, _2, _3, &state_), 43 | true /* supports_notification */, nullptr /* write_handler */, 44 | kHAPCharacteristicDebugDescription_OccupancyDetected)); 45 | return Status::OK(); 46 | } 47 | 48 | } // namespace hap 49 | } // namespace shelly 50 | -------------------------------------------------------------------------------- /src/shelly_hap_occupancy_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_hap_sensor_base.hpp" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | class OccupancySensor : public SensorBase { 26 | public: 27 | OccupancySensor(int id, Input *in, struct mgos_config_in_sensor *cfg); 28 | virtual ~OccupancySensor(); 29 | 30 | // Component interface impl. 31 | Status Init() override; 32 | virtual Type type() const override; 33 | }; 34 | 35 | } // namespace hap 36 | } // namespace shelly 37 | -------------------------------------------------------------------------------- /src/shelly_hap_outlet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_outlet.hpp" 19 | 20 | namespace shelly { 21 | namespace hap { 22 | 23 | Outlet::Outlet(int id, Input *in, Output *out, PowerMeter *out_pm, 24 | Output *led_out, struct mgos_config_sw *cfg) 25 | : ShellySwitch(id, in, out, out_pm, led_out, cfg) { 26 | } 27 | 28 | Outlet::~Outlet() { 29 | } 30 | 31 | Status Outlet::Init() { 32 | auto st = ShellySwitch::Init(); 33 | if (!st.ok()) return st; 34 | 35 | const int id1 = id() - 1; // IDs used to start at 0, preserve compat. 36 | uint16_t iid = 37 | SHELLY_HAP_IID_BASE_OUTLET + (SHELLY_HAP_IID_STEP_OUTLET * id1); 38 | svc_.iid = iid++; 39 | svc_.serviceType = &kHAPServiceType_Outlet; 40 | svc_.debugDescription = kHAPServiceDebugDescription_Outlet; 41 | // Name 42 | AddNameChar(iid++, cfg_->name); 43 | // On 44 | auto *on_char = new mgos::hap::BoolCharacteristic( 45 | iid++, &kHAPCharacteristicType_On, 46 | [this](HAPAccessoryServerRef *, const HAPBoolCharacteristicReadRequest *, 47 | bool *value) { 48 | *value = out_->GetState() ^ cfg_->hk_state_inverted; 49 | return kHAPError_None; 50 | }, 51 | true /* supports_notification */, 52 | [this](HAPAccessoryServerRef *, const HAPBoolCharacteristicWriteRequest *, 53 | bool value) { 54 | SetOutputState(value ^ cfg_->hk_state_inverted, "HAP"); 55 | return kHAPError_None; 56 | }, 57 | kHAPCharacteristicDebugDescription_On); 58 | state_notify_chars_.push_back(on_char); 59 | AddChar(on_char); 60 | // Outlet In Use 61 | AddChar(new mgos::hap::BoolCharacteristic( 62 | iid++, &kHAPCharacteristicType_OutletInUse, 63 | [](HAPAccessoryServerRef *, const HAPBoolCharacteristicReadRequest *, 64 | bool *value) { 65 | *value = true; 66 | return kHAPError_None; 67 | }, 68 | true /* supports_notification */, nullptr /* write_handler */, 69 | kHAPCharacteristicDebugDescription_OutletInUse)); 70 | 71 | // Power 72 | AddPowerMeter(&iid); 73 | 74 | return Status::OK(); 75 | } 76 | 77 | } // namespace hap 78 | } // namespace shelly 79 | -------------------------------------------------------------------------------- /src/shelly_hap_outlet.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_switch.hpp" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | class Outlet : public ShellySwitch { 26 | public: 27 | Outlet(int id, Input *in, Output *out, PowerMeter *out_pm, Output *led_out, 28 | struct mgos_config_sw *cfg); 29 | virtual ~Outlet(); 30 | 31 | Status Init(); 32 | }; 33 | 34 | } // namespace hap 35 | } // namespace shelly 36 | -------------------------------------------------------------------------------- /src/shelly_hap_sensor_base.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "mgos_hap_service.hpp" 21 | #include "mgos_sys_config.h" 22 | #include "mgos_timers.hpp" 23 | 24 | #include "shelly_common.hpp" 25 | #include "shelly_component.hpp" 26 | #include "shelly_input.hpp" 27 | 28 | namespace shelly { 29 | namespace hap { 30 | 31 | class SensorBase : public Component, public mgos::hap::Service { 32 | public: 33 | enum class InMode { 34 | kLevel = 0, 35 | kPulse = 1, 36 | kMax, 37 | }; 38 | 39 | SensorBase(int id, Input *in, struct mgos_config_in_sensor *cfg, 40 | uint16_t iid_base, const HAPUUID *type, 41 | const char *debug_description); 42 | virtual ~SensorBase(); 43 | 44 | // Component interface impl. 45 | virtual Status Init() override; 46 | std::string name() const override; 47 | StatusOr GetInfo() const override; 48 | StatusOr GetInfoJSON() const override; 49 | Status SetConfig(const std::string &config_json, 50 | bool *restart_required) override; 51 | Status SetState(const std::string &state_json) override; 52 | 53 | protected: 54 | bool state_ = false; 55 | 56 | private: 57 | void InputEventHandler(Input::Event ev, bool state); 58 | void SetInternalState(bool motion_detected); 59 | void AutoOffTimerCB(); 60 | 61 | Input *const in_; 62 | struct mgos_config_in_sensor *cfg_; 63 | 64 | Input::HandlerID handler_id_ = Input::kInvalidHandlerID; 65 | 66 | double last_ev_ts_ = 0; 67 | mgos::Timer auto_off_timer_; 68 | 69 | SensorBase(const SensorBase &other) = delete; 70 | }; 71 | 72 | } // namespace hap 73 | } // namespace shelly 74 | -------------------------------------------------------------------------------- /src/shelly_hap_smoke_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_smoke_sensor.hpp" 19 | 20 | namespace shelly { 21 | namespace hap { 22 | 23 | SmokeSensor::SmokeSensor(int id, Input *in, struct mgos_config_in_sensor *cfg) 24 | : SensorBase(id, in, cfg, SHELLY_HAP_IID_BASE_SMOKE_SENSOR, 25 | &kHAPServiceType_SmokeSensor, 26 | kHAPServiceDebugDescription_SmokeSensor) { 27 | } 28 | 29 | SmokeSensor::~SmokeSensor() { 30 | } 31 | 32 | Component::Type SmokeSensor::type() const { 33 | return Type::kSmokeSensor; 34 | } 35 | 36 | Status SmokeSensor::Init() { 37 | const Status &st = SensorBase::Init(); 38 | if (!st.ok()) return st; 39 | AddChar(new mgos::hap::UInt8Characteristic( 40 | svc_.iid + 2, &kHAPCharacteristicType_SmokeDetected, 0, 1, 1, 41 | std::bind(&mgos::hap::ReadUInt8, _1, _2, _3, &state_), 42 | true /* supports_notification */, nullptr /* write_handler */, 43 | kHAPCharacteristicDebugDescription_SmokeDetected)); 44 | return Status::OK(); 45 | } 46 | 47 | } // namespace hap 48 | } // namespace shelly 49 | -------------------------------------------------------------------------------- /src/shelly_hap_smoke_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_hap_sensor_base.hpp" 21 | 22 | namespace shelly { 23 | namespace hap { 24 | 25 | class SmokeSensor : public SensorBase { 26 | public: 27 | SmokeSensor(int id, Input *in, struct mgos_config_in_sensor *cfg); 28 | virtual ~SmokeSensor(); 29 | 30 | // Component interface impl. 31 | Status Init() override; 32 | virtual Type type() const override; 33 | }; 34 | 35 | } // namespace hap 36 | } // namespace shelly 37 | -------------------------------------------------------------------------------- /src/shelly_hap_stateless_switch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_stateless_switch.hpp" 19 | 20 | namespace shelly { 21 | namespace hap { 22 | 23 | StatelessSwitch::StatelessSwitch(int id, Input *in, 24 | struct mgos_config_in_ssw *cfg) 25 | : StatelessSwitchBase( 26 | id, in, cfg, SHELLY_HAP_IID_BASE_STATELESS_SWITCH, 27 | &kHAPServiceType_StatelessProgrammableSwitch, 28 | kHAPServiceDebugDescription_StatelessProgrammableSwitch) { 29 | } 30 | 31 | StatelessSwitch::~StatelessSwitch() { 32 | } 33 | 34 | Component::Type StatelessSwitch::type() const { 35 | return Type::kStatelessSwitch; 36 | } 37 | 38 | } // namespace hap 39 | } // namespace shelly -------------------------------------------------------------------------------- /src/shelly_hap_stateless_switch.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | #include "shelly_hap_stateless_switch_base.hpp" 20 | 21 | namespace shelly { 22 | namespace hap { 23 | 24 | class StatelessSwitch : public StatelessSwitchBase { 25 | public: 26 | StatelessSwitch(int id, Input *in, struct mgos_config_in_ssw *cfg); 27 | virtual ~StatelessSwitch(); 28 | 29 | // Component interface impl. 30 | Type type() const override; 31 | }; 32 | 33 | } // namespace hap 34 | } // namespace shelly -------------------------------------------------------------------------------- /src/shelly_hap_stateless_switch_base.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "mgos_hap.hpp" 24 | #include "mgos_sys_config.h" 25 | #include "mgos_timers.h" 26 | 27 | #include "shelly_common.hpp" 28 | #include "shelly_component.hpp" 29 | #include "shelly_input.hpp" 30 | #include "shelly_output.hpp" 31 | #include "shelly_pm.hpp" 32 | 33 | namespace shelly { 34 | namespace hap { 35 | 36 | // Common base for Switch, Outlet and Lock services. 37 | class StatelessSwitchBase : public Component, public mgos::hap::Service { 38 | public: 39 | enum class InMode { 40 | kMomentary = 0, 41 | kToggleShort = 1, 42 | kToggleShortLong = 2, 43 | }; 44 | 45 | StatelessSwitchBase(int id, Input *in, struct mgos_config_in_ssw *cfg, 46 | uint16_t iid_base, const HAPUUID *type, 47 | const char *debug_description); 48 | virtual ~StatelessSwitchBase(); 49 | 50 | // Component interface impl. 51 | Status Init() override; 52 | Type type() const override; 53 | std::string name() const override; 54 | StatusOr GetInfo() const override; 55 | StatusOr GetInfoJSON() const override; 56 | Status SetConfig(const std::string &config_json, 57 | bool *restart_required) override; 58 | Status SetState(const std::string &state_json) override; 59 | 60 | private: 61 | void InputEventHandler(Input::Event ev, bool state); 62 | 63 | void RaiseEvent(uint8_t ev); 64 | 65 | Input *const in_; 66 | struct mgos_config_in_ssw *cfg_; 67 | 68 | Input::HandlerID handler_id_ = Input::kInvalidHandlerID; 69 | 70 | uint8_t last_ev_ = 0; 71 | double last_ev_ts_ = 0; 72 | 73 | StatelessSwitchBase(const StatelessSwitchBase &other) = delete; 74 | }; 75 | 76 | } // namespace hap 77 | } // namespace shelly 78 | -------------------------------------------------------------------------------- /src/shelly_hap_switch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_hap_switch.hpp" 19 | 20 | #include "mgos.hpp" 21 | #include "mgos_hap_chars.hpp" 22 | 23 | namespace shelly { 24 | namespace hap { 25 | 26 | Switch::Switch(int id, Input *in, Output *out, PowerMeter *out_pm, 27 | Output *led_out, struct mgos_config_sw *cfg) 28 | : ShellySwitch(id, in, out, out_pm, led_out, cfg) { 29 | } 30 | 31 | Switch::~Switch() { 32 | } 33 | 34 | Status Switch::Init() { 35 | auto st = ShellySwitch::Init(); 36 | if (!st.ok()) return st; 37 | 38 | const int id1 = id() - 1; // IDs used to start at 0, preserve compat. 39 | uint16_t iid = 40 | SHELLY_HAP_IID_BASE_SWITCH + (SHELLY_HAP_IID_STEP_SWITCH * id1); 41 | svc_.iid = iid++; 42 | svc_.serviceType = &kHAPServiceType_Switch; 43 | svc_.debugDescription = kHAPServiceDebugDescription_Switch; 44 | // Name 45 | AddNameChar(iid++, cfg_->name); 46 | // On 47 | auto *on_char = new mgos::hap::BoolCharacteristic( 48 | iid++, &kHAPCharacteristicType_On, 49 | [this](HAPAccessoryServerRef *, const HAPBoolCharacteristicReadRequest *, 50 | bool *value) { 51 | *value = out_->GetState() ^ cfg_->hk_state_inverted; 52 | return kHAPError_None; 53 | }, 54 | true /* supports_notification */, 55 | [this](HAPAccessoryServerRef *, const HAPBoolCharacteristicWriteRequest *, 56 | bool value) { 57 | SetOutputState(value ^ cfg_->hk_state_inverted, "HAP"); 58 | return kHAPError_None; 59 | }, 60 | kHAPCharacteristicDebugDescription_On); 61 | state_notify_chars_.push_back(on_char); 62 | AddChar(on_char); 63 | 64 | // Power 65 | AddPowerMeter(&iid); 66 | 67 | out_->SetInvert(cfg_->out_inverted); 68 | 69 | return Status::OK(); 70 | } 71 | 72 | } // namespace hap 73 | } // namespace shelly 74 | -------------------------------------------------------------------------------- /src/shelly_hap_switch.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "mgos_hap.hpp" 24 | #include "mgos_sys_config.h" 25 | #include "mgos_timers.h" 26 | 27 | #include "shelly_common.hpp" 28 | #include "shelly_component.hpp" 29 | #include "shelly_input.hpp" 30 | #include "shelly_output.hpp" 31 | #include "shelly_pm.hpp" 32 | #include "shelly_switch.hpp" 33 | 34 | namespace shelly { 35 | namespace hap { 36 | 37 | class Switch : public ShellySwitch { 38 | public: 39 | Switch(int id, Input *in, Output *out, PowerMeter *out_pm, Output *led_out, 40 | struct mgos_config_sw *cfg); 41 | virtual ~Switch(); 42 | 43 | Status Init(); 44 | }; 45 | 46 | } // namespace hap 47 | } // namespace shelly 48 | -------------------------------------------------------------------------------- /src/shelly_hap_temperature_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "mgos_hap_service.hpp" 21 | #include "mgos_sys_config.h" 22 | 23 | #include "shelly_common.hpp" 24 | #include "shelly_component.hpp" 25 | 26 | #include "shelly_temp_sensor.hpp" 27 | 28 | namespace shelly { 29 | namespace hap { 30 | 31 | class TemperatureSensor : public Component, public mgos::hap::Service { 32 | public: 33 | TemperatureSensor(int id, TempSensor *sensor, struct mgos_config_ts *cfg); 34 | virtual ~TemperatureSensor(); 35 | 36 | // Component interface impl. 37 | Type type() const override; 38 | std::string name() const override; 39 | Status Init() override; 40 | 41 | StatusOr GetInfo() const override; 42 | StatusOr GetInfoJSON() const override; 43 | Status SetConfig(const std::string &config_json, 44 | bool *restart_required) override; 45 | Status SetState(const std::string &state_json) override; 46 | 47 | private: 48 | TempSensor *temp_sensor_; 49 | struct mgos_config_ts *cfg_; 50 | 51 | mgos::hap::FloatCharacteristic *current_temperature_characteristic_; 52 | 53 | void ValueChanged(); 54 | }; 55 | 56 | void CreateHAPTemperatureSensor( 57 | int id, TempSensor *sensor, const struct mgos_config_ts *ts_cfg, 58 | std::vector> *comps, 59 | std::vector> *accs, 60 | HAPAccessoryServerRef *svr); 61 | 62 | } // namespace hap 63 | } // namespace shelly 64 | -------------------------------------------------------------------------------- /src/shelly_hap_valve.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "mgos_hap_chars.hpp" 21 | #include "shelly_switch.hpp" 22 | 23 | namespace shelly { 24 | namespace hap { 25 | 26 | class Valve : public ShellySwitch { 27 | public: 28 | Valve(int id, Input *in, Output *out, PowerMeter *out_pm, Output *led_out, 29 | struct mgos_config_sw *cfg); 30 | virtual ~Valve(); 31 | 32 | Status Init() override; 33 | }; 34 | 35 | } // namespace hap 36 | } // namespace shelly 37 | -------------------------------------------------------------------------------- /src/shelly_input.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_input.hpp" 19 | 20 | namespace shelly { 21 | 22 | // static 23 | constexpr Input::HandlerID Input::kInvalidHandlerID; 24 | 25 | Input::Input(int id) : id_(id) { 26 | } 27 | 28 | Input::~Input() { 29 | } 30 | 31 | // static 32 | const char *Input::EventName(Event ev) { 33 | switch (ev) { 34 | case Event::kChange: 35 | return "change"; 36 | case Event::kSingle: 37 | return "single"; 38 | case Event::kDouble: 39 | return "double"; 40 | case Event::kLong: 41 | return "long"; 42 | case Event::kReset: 43 | return "reset"; 44 | case Event::kMax: 45 | break; 46 | } 47 | return ""; 48 | } 49 | 50 | int Input::id() const { 51 | return id_; 52 | } 53 | 54 | Input::HandlerID Input::AddHandler(HandlerFn h) { 55 | int i; 56 | for (i = 0; i < (int) handlers_.size(); i++) { 57 | if (handlers_[i] == nullptr) { 58 | handlers_[i] = h; 59 | return i; 60 | } 61 | } 62 | handlers_.push_back(h); 63 | return i; 64 | } 65 | 66 | void Input::RemoveHandler(HandlerID hi) { 67 | if (hi < 0) return; 68 | handlers_[hi] = nullptr; 69 | } 70 | 71 | void Input::InjectEvent(Event ev, bool state) { 72 | CallHandlers(ev, state, true /* injected */); 73 | } 74 | 75 | void Input::CallHandlers(Event ev, bool state, bool injected) { 76 | LOG(LL_INFO, ("Input %d: %s (state %d)%s", id(), EventName(ev), state, 77 | (injected ? " [injected]" : ""))); 78 | for (auto &h : handlers_) { 79 | if (h != nullptr) h(ev, state); 80 | } 81 | } 82 | 83 | } // namespace shelly 84 | -------------------------------------------------------------------------------- /src/shelly_input.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "shelly_common.hpp" 23 | 24 | namespace shelly { 25 | 26 | class Input { 27 | public: 28 | enum class Event { 29 | kChange = 0, 30 | kSingle = 1, 31 | kDouble = 2, 32 | kLong = 3, 33 | kReset = 4, 34 | kMax, 35 | }; 36 | explicit Input(int id); 37 | virtual ~Input(); 38 | 39 | static const char *EventName(Event ev); 40 | 41 | int id() const; 42 | virtual void Init() = 0; 43 | virtual bool GetState() = 0; 44 | virtual void SetInvert(bool invert) = 0; 45 | 46 | typedef int HandlerID; 47 | static constexpr HandlerID kInvalidHandlerID = -1; 48 | typedef std::function HandlerFn; 49 | HandlerID AddHandler(HandlerFn h); 50 | void RemoveHandler(HandlerID hi); 51 | 52 | void InjectEvent(Event ev, bool state); 53 | 54 | protected: 55 | void CallHandlers(Event ev, bool state, bool injected = false); 56 | 57 | private: 58 | const int id_; 59 | std::vector handlers_; 60 | 61 | Input(const Input &other) = delete; 62 | }; 63 | 64 | } // namespace shelly 65 | -------------------------------------------------------------------------------- /src/shelly_input_pin.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_input.hpp" 21 | 22 | #include "mgos_gpio.h" 23 | #include "mgos_timers.hpp" 24 | 25 | namespace shelly { 26 | 27 | class InputPin : public Input { 28 | public: 29 | static constexpr int kDefaultShortPressDurationMs = 500; 30 | static constexpr int kDefaultLongPressDurationMs = 1000; 31 | 32 | struct Config { 33 | int pin; 34 | int on_value; 35 | enum mgos_gpio_pull_type pull; 36 | bool enable_reset; 37 | int short_press_duration_ms; 38 | int long_press_duration_ms; 39 | }; 40 | 41 | InputPin(int id, int pin, int on_value, enum mgos_gpio_pull_type pull, 42 | bool enable_reset); 43 | InputPin(int id, const Config &cfg); 44 | virtual ~InputPin(); 45 | 46 | // Input interface impl. 47 | bool GetState() override; 48 | virtual void Init() override; 49 | void SetInvert(bool invert) override; 50 | 51 | protected: 52 | virtual bool ReadPin(); 53 | void HandleGPIOInt(); 54 | 55 | const Config cfg_; 56 | bool invert_ = false; 57 | 58 | private: 59 | enum class State { 60 | kIdle = 0, 61 | kWaitOffSingle = 1, 62 | kWaitOnDouble = 2, 63 | kWaitOffDouble = 3, 64 | kWaitOffLong = 4, 65 | }; 66 | 67 | static void GPIOIntHandler(int pin, void *arg); 68 | 69 | void DetectReset(double now, bool cur_state); 70 | 71 | void HandleTimer(); 72 | 73 | bool last_state_ = false; 74 | int change_cnt_ = 0; // State change counter for reset. 75 | double last_change_ts_ = 0; // Timestamp of last change (uptime). 76 | 77 | State state_ = State::kIdle; 78 | int timer_cnt_ = 0; 79 | mgos::Timer timer_; 80 | 81 | InputPin(const InputPin &other) = delete; 82 | }; 83 | 84 | } // namespace shelly 85 | -------------------------------------------------------------------------------- /src/shelly_light_bulb_controller.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "mgos_sys_config.h" 24 | #include "mgos_timers.hpp" 25 | 26 | #include "shelly_common.hpp" 27 | 28 | namespace shelly { 29 | 30 | class LightBulbControllerBase { 31 | public: 32 | enum class BulbType { 33 | kWhite = 0, 34 | kCCT = 1, 35 | kRGBW = 2, 36 | kMax = 3, 37 | }; 38 | typedef std::function 40 | UpdateFn; 41 | 42 | LightBulbControllerBase(struct mgos_config_lb *cfg, UpdateFn ud); 43 | LightBulbControllerBase(const LightBulbControllerBase &other) = delete; 44 | virtual ~LightBulbControllerBase(); 45 | 46 | void UpdateOutput(struct mgos_config_lb *cfg, bool cancel_previous) const; 47 | 48 | virtual BulbType Type() = 0; 49 | 50 | bool IsOn() const; 51 | bool IsOff() const; 52 | 53 | protected: 54 | struct mgos_config_lb *cfg_; 55 | const UpdateFn update_; 56 | }; 57 | 58 | template 59 | struct Transition { 60 | T state_end; 61 | int64_t transition_time_micros = 0; 62 | }; 63 | 64 | template 65 | class LightBulbController : public LightBulbControllerBase { 66 | public: 67 | LightBulbController(struct mgos_config_lb *cfg) 68 | : LightBulbControllerBase( 69 | cfg, std::bind(&LightBulbController::UpdateOutputSpecialized, 70 | this, _1, _2)), 71 | transition_timer_( 72 | std::bind(&LightBulbController::TransitionTimerCB, this)) { 73 | } 74 | LightBulbController(const LightBulbControllerBase &other) = delete; 75 | 76 | private: 77 | mgos::Timer transition_timer_; 78 | int64_t transition_start_ = 0; 79 | 80 | T state_start_{}; 81 | T state_now_{}; 82 | 83 | std::deque> transitions_; 84 | 85 | virtual T ConfigToState(const struct mgos_config_lb &cfg) const = 0; 86 | virtual void ReportTransition(const T &next, const T &prev) = 0; 87 | virtual void UpdatePWM(const T &state) = 0; 88 | 89 | void StartPendingTransitions(); 90 | void TransitionTimerCB(); 91 | void UpdateOutputSpecialized(const struct mgos_config_lb &cfg, 92 | bool cancel_previous); 93 | }; 94 | } // namespace shelly 95 | -------------------------------------------------------------------------------- /src/shelly_main.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "mgos_sys_config.h" 24 | 25 | #include "mgos_hap_accessory.hpp" 26 | #include "mgos_hap_service.hpp" 27 | #include "shelly_component.hpp" 28 | #include "shelly_input.hpp" 29 | #include "shelly_output.hpp" 30 | #include "shelly_pm.hpp" 31 | #include "shelly_reset.hpp" 32 | #include "shelly_temp_sensor.hpp" 33 | 34 | #define AUTH_USER "admin" 35 | #define AUTH_FILE_NAME "passwd256" 36 | #define ACL_FILE_NAME "rpc_acl.json" 37 | #define KVS_FILE_NAME "kvs.json" 38 | 39 | namespace shelly { 40 | 41 | extern std::vector> g_comps; 42 | 43 | bool DetectAddon(int pin_in, int pin_out); 44 | void RestoreUART(); 45 | Input *FindInput(int id); 46 | Output *FindOutput(int id); 47 | PowerMeter *FindPM(int id); 48 | 49 | void CreateHAPSensors(std::vector> *sensors, 50 | std::vector> *comps, 51 | std::vector> *accs, 52 | HAPAccessoryServerRef *svr); 53 | 54 | void CreateHAPSwitch(int id, const struct mgos_config_sw *sw_cfg, 55 | const struct mgos_config_in *in_cfg, 56 | std::vector> *comps, 57 | std::vector> *accs, 58 | HAPAccessoryServerRef *svr, bool to_pri_acc, 59 | Output *led_out = nullptr); 60 | 61 | void HandleInputResetSequence(Input *in, int out_gpio, Input::Event ev, 62 | bool cur_state); 63 | 64 | void StopService(); 65 | void RestartService(); 66 | bool IsServiceRunning(); 67 | bool IsPaired(); 68 | 69 | bool AllComponentsIdle(); 70 | 71 | StatusOr GetSystemTemperature(); 72 | 73 | #define SHELLY_SERVICE_FLAG_UPDATE (1 << 0) 74 | #define SHELLY_SERVICE_FLAG_REBOOT (1 << 1) 75 | #define SHELLY_SERVICE_FLAG_OVERHEAT (1 << 2) 76 | #define SHELLY_SERVICE_FLAG_REVERT (1 << 3) 77 | uint8_t GetServiceFlags(); 78 | void SetServiceFlags(uint8_t flags); 79 | void ClearServiceFlags(uint8_t flags); 80 | 81 | mgos::hap::Accessory::IdentifyCB GetIdentifyCB(); 82 | void SetIdentifyCB(mgos::hap::Accessory::IdentifyCB cb); 83 | 84 | // Implemented for each model. 85 | 86 | void CreatePeripherals(std::vector> *inputs, 87 | std::vector> *outputs, 88 | std::vector> *pms, 89 | std::unique_ptr *sys_temp); 90 | 91 | void CreateComponents(std::vector> *comps, 92 | std::vector> *accs, 93 | HAPAccessoryServerRef *svr); 94 | 95 | } // namespace shelly 96 | -------------------------------------------------------------------------------- /src/shelly_noisy_input_pin.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_input_pin.hpp" 21 | 22 | namespace shelly { 23 | 24 | class NoisyInputPin : public InputPin { 25 | public: 26 | NoisyInputPin(int id, int pin, int on_value, enum mgos_gpio_pull_type pull, 27 | bool enable_reset); 28 | NoisyInputPin(int id, const InputPin::Config &cfg); 29 | virtual ~NoisyInputPin(); 30 | 31 | void Init() override; 32 | 33 | void Check(); 34 | 35 | private: 36 | bool ReadPin() override; 37 | }; 38 | 39 | } // namespace shelly 40 | -------------------------------------------------------------------------------- /src/shelly_ota.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "HAP.h" 23 | 24 | #include "shelly_common.hpp" 25 | 26 | namespace shelly { 27 | 28 | struct OTAProgress { 29 | std::string version; 30 | std::string build; 31 | int progress_pct = -1; 32 | 33 | OTAProgress() = default; 34 | OTAProgress(const std::string &version, const std::string &build); 35 | }; 36 | StatusOr GetOTAProgress(); 37 | 38 | void OTAInit(HAPAccessoryServerRef *server); 39 | 40 | } // namespace shelly 41 | -------------------------------------------------------------------------------- /src/shelly_output.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_output.hpp" 19 | 20 | #include "mgos.hpp" 21 | #include "mgos_gpio.h" 22 | 23 | #if CS_PLATFORM != CS_P_ESP8266 24 | #include "driver/gpio.h" 25 | #endif 26 | 27 | #ifdef MGOS_HAVE_PWM 28 | #include "mgos_pwm.h" 29 | #endif 30 | 31 | namespace shelly { 32 | 33 | Output::Output(int id) : id_(id) { 34 | } 35 | 36 | Output::~Output() { 37 | } 38 | 39 | int Output::id() const { 40 | return id_; 41 | } 42 | 43 | OutputPin::OutputPin(int id, int pin, int on_value) 44 | : Output(id), 45 | pin_(pin), 46 | on_value_(on_value), 47 | pulse_timer_(std::bind(&OutputPin::PulseTimerCB, this)) { 48 | mgos_gpio_set_mode(pin_, MGOS_GPIO_MODE_OUTPUT); 49 | #if CS_PLATFORM != CS_P_ESP8266 50 | gpio_hold_dis((gpio_num_t) pin); 51 | #endif 52 | LOG(LL_INFO, ("OutputPin %d: pin %d, on_value %d, state %s", id, pin, 53 | on_value, OnOff(GetState()))); 54 | } 55 | 56 | OutputPin::~OutputPin() { 57 | #if CS_PLATFORM != CS_P_ESP8266 58 | gpio_hold_en((gpio_num_t) pin_); 59 | #endif 60 | } 61 | 62 | bool OutputPin::GetState() { 63 | return (mgos_gpio_read_out(pin_) == on_value_) ^ out_invert_; 64 | } 65 | 66 | int OutputPin::pin() const { 67 | return pin_; 68 | } 69 | 70 | Status OutputPin::SetState(bool on, const char *source) { 71 | bool cur_state = GetState(); 72 | mgos_gpio_write(pin_, ((on ^ out_invert_) ? on_value_ : !on_value_)); 73 | pulse_active_ = false; 74 | if (on == cur_state) return Status::OK(); 75 | if (source == nullptr) source = ""; 76 | LOG(LL_INFO, 77 | ("Output %d: %s -> %s (%s)", id(), OnOff(cur_state), OnOff(on), source)); 78 | return Status::OK(); 79 | } 80 | 81 | Status OutputPin::SetStatePWM(float duty, const char *source) { 82 | #ifdef MGOS_HAVE_PWM 83 | LOG(LL_INFO, ("Duty: %.3f", duty)); 84 | if (duty == 0) { 85 | mgos_pwm_set(pin_, 0, 0); 86 | } 87 | #if CS_PLATFORM == CS_P_ESP8266 88 | else if (duty == 1) { 89 | mgos_gpio_write(pin_, 1); 90 | LOG(LL_INFO, 91 | ("Output %d: %s (%s)", id(), (duty == 0 ? "OFF" : "ON"), source)); 92 | } 93 | #endif 94 | else { 95 | mgos_pwm_set(pin_, 400, duty); 96 | LOG(LL_INFO, ("Output %d: %f (%s)", id(), duty, source)); 97 | } 98 | return Status::OK(); 99 | #else 100 | (void) duty; 101 | (void) source; 102 | return Status::UNIMPLEMENTED(); 103 | #endif 104 | } 105 | 106 | Status OutputPin::Pulse(bool on, int duration_ms, const char *source) { 107 | Status st = SetState(on, source); 108 | if (!st.ok()) return st; 109 | pulse_timer_.Reset(duration_ms, 0); 110 | pulse_active_ = true; 111 | return Status::OK(); 112 | } 113 | 114 | void OutputPin::PulseTimerCB() { 115 | if (!pulse_active_) return; 116 | SetState(!GetState(), "pulse_off"); 117 | } 118 | 119 | void OutputPin::SetInvert(bool out_invert) { 120 | out_invert_ = out_invert; 121 | GetState(); 122 | } 123 | 124 | } // namespace shelly 125 | -------------------------------------------------------------------------------- /src/shelly_output.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_common.hpp" 21 | 22 | #include "mgos_timers.hpp" 23 | 24 | namespace shelly { 25 | 26 | class Output { 27 | public: 28 | explicit Output(int id); 29 | virtual ~Output(); 30 | 31 | int id() const; 32 | virtual bool GetState() = 0; 33 | virtual Status SetState(bool on, const char *source) = 0; 34 | virtual Status SetStatePWM(float duty, const char *source) = 0; 35 | virtual Status Pulse(bool on, int duration_ms, const char *source) = 0; 36 | virtual void SetInvert(bool out_invert) = 0; 37 | 38 | private: 39 | const int id_; 40 | Output(const Output &other) = delete; 41 | }; 42 | 43 | class OutputPin : public Output { 44 | public: 45 | OutputPin(int id, int pin, int on_value); 46 | virtual ~OutputPin(); 47 | 48 | // Output interface impl. 49 | bool GetState() override; 50 | Status SetState(bool on, const char *source) override; 51 | Status SetStatePWM(float duty, const char *source) override; 52 | Status Pulse(bool on, int duration_ms, const char *source) override; 53 | int pin() const; 54 | void SetInvert(bool out_invert) override; 55 | 56 | protected: 57 | bool out_invert_ = false; 58 | 59 | private: 60 | void PulseTimerCB(); 61 | 62 | const int pin_; 63 | const int on_value_; 64 | 65 | bool pulse_active_ = false; 66 | mgos::Timer pulse_timer_; 67 | 68 | OutputPin(const OutputPin &other) = delete; 69 | }; 70 | 71 | } // namespace shelly 72 | -------------------------------------------------------------------------------- /src/shelly_pm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_pm.hpp" 19 | 20 | namespace shelly { 21 | 22 | PowerMeter::PowerMeter(int id) : id_(id) { 23 | } 24 | 25 | PowerMeter::~PowerMeter() { 26 | } 27 | 28 | int PowerMeter::id() const { 29 | return id_; 30 | } 31 | 32 | } // namespace shelly 33 | -------------------------------------------------------------------------------- /src/shelly_pm.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "shelly_common.hpp" 24 | 25 | namespace shelly { 26 | 27 | class PowerMeter { 28 | public: 29 | explicit PowerMeter(int id); 30 | virtual ~PowerMeter(); 31 | 32 | int id() const; 33 | 34 | virtual Status Init() = 0; 35 | virtual StatusOr GetPowerW() = 0; 36 | virtual StatusOr GetEnergyWH() = 0; 37 | 38 | private: 39 | const int id_; 40 | 41 | PowerMeter(const PowerMeter &other) = delete; 42 | }; 43 | 44 | } // namespace shelly 45 | -------------------------------------------------------------------------------- /src/shelly_rgbw_controller.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "mgos_timers.hpp" 19 | #include "shelly_light_bulb_controller.hpp" 20 | #include "shelly_output.hpp" 21 | 22 | #pragma once 23 | 24 | namespace shelly { 25 | struct StateRGBW { 26 | float r; 27 | float g; 28 | float b; 29 | float w; 30 | 31 | StateRGBW operator+(const StateRGBW &other) const { 32 | return { 33 | .r = r + other.r, 34 | .g = g + other.g, 35 | .b = b + other.b, 36 | .w = w + other.w, 37 | }; 38 | } 39 | 40 | StateRGBW operator*(float a) const { 41 | return { 42 | .r = a * r, 43 | .g = a * g, 44 | .b = a * b, 45 | .w = a * w, 46 | }; 47 | } 48 | 49 | std::string ToString() const; 50 | }; 51 | 52 | class RGBWController : public LightBulbController { 53 | public: 54 | RGBWController(struct mgos_config_lb *cfg, Output *out_r, Output *out_g, 55 | Output *out_b, Output *out_w); 56 | RGBWController(const RGBWController &other) = delete; 57 | ~RGBWController(); 58 | 59 | BulbType Type() final { 60 | return BulbType::kRGBW; 61 | } 62 | 63 | private: 64 | Output *const out_r_, *const out_g_, *const out_b_, *const out_w_; 65 | StateRGBW ConfigToState(const struct mgos_config_lb &cfg) const final; 66 | void ReportTransition(const StateRGBW &next, const StateRGBW &prev) final; 67 | void UpdatePWM(const StateRGBW &state) final; 68 | }; 69 | } // namespace shelly 70 | -------------------------------------------------------------------------------- /src/shelly_rpc_service.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_common.hpp" 19 | 20 | #include "HAP.h" 21 | 22 | extern "C" struct mg_rpc_request_info; 23 | 24 | namespace shelly { 25 | 26 | void SendStatusResp(struct mg_rpc_request_info *ri, const Status &st); 27 | 28 | void ReportRPCRequest(struct mg_rpc_request_info *ri); 29 | 30 | bool RPCServiceInit(HAPAccessoryServerRef *server, 31 | HAPPlatformKeyValueStoreRef kvs, 32 | HAPPlatformTCPStreamManagerRef tcpm); 33 | 34 | } // namespace shelly 35 | -------------------------------------------------------------------------------- /src/shelly_statusled.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #include "shelly_statusled.hpp" 18 | 19 | #ifdef MGOS_CONFIG_HAVE_LED 20 | 21 | namespace shelly { 22 | 23 | StatusLED::StatusLED(int id, int pin, int num_pixel, 24 | enum mgos_neopixel_order pixel_type, Output *chained_led, 25 | const struct mgos_config_led *cfg) 26 | : Output(id), 27 | pin_(pin), 28 | num_pixel_(num_pixel), 29 | chained_led_(chained_led), 30 | cfg_(cfg) { 31 | pixel_ = mgos_neopixel_create(pin_, num_pixel_, pixel_type); 32 | value_ = false; 33 | } 34 | 35 | StatusLED::~StatusLED() { 36 | mgos_neopixel_free(pixel_); 37 | } 38 | 39 | bool StatusLED::GetState() { 40 | return value_; 41 | } 42 | 43 | int StatusLED::pin() const { 44 | return pin_; 45 | } 46 | 47 | struct rgb { 48 | int r; 49 | int g; 50 | int b; 51 | }; 52 | 53 | Status StatusLED::SetState(bool on, const char *source) { 54 | if (chained_led_ != nullptr) { 55 | chained_led_->SetState(on, source); 56 | } 57 | value_ = on; 58 | // get color from config 59 | struct rgb colorOn = {(cfg_->color_on >> 16) & 0xFF, 60 | (cfg_->color_on >> 8) & 0xFF, 61 | (cfg_->color_on >> 0) & 0xFF}; 62 | struct rgb colorOff = {(cfg_->color_off >> 16) & 0xFF, 63 | (cfg_->color_off >> 8) & 0xFF, 64 | (cfg_->color_off >> 0) & 0xFF}; 65 | 66 | struct rgb color = on ? colorOn : colorOff; 67 | 68 | for (int i = 0; i < num_pixel_; i++) { 69 | mgos_neopixel_set(pixel_, i, color.r, color.b, color.g); 70 | } 71 | mgos_neopixel_show(pixel_); 72 | return Status::OK(); 73 | } 74 | 75 | } // namespace shelly 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/shelly_statusled.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "mgos_config.h" 19 | 20 | #ifdef MGOS_CONFIG_HAVE_LED 21 | 22 | #pragma once 23 | 24 | #include "shelly_output.hpp" 25 | 26 | #include "mgos_neopixel.h" 27 | 28 | namespace shelly { 29 | 30 | class StatusLED : public Output { 31 | public: 32 | StatusLED(int id, int pin, int num_pixel, enum mgos_neopixel_order pixel_type, 33 | Output *chained_led, const struct mgos_config_led *cfg); 34 | virtual ~StatusLED(); 35 | 36 | // Output interface impl. 37 | bool GetState() override; 38 | Status SetState(bool on, const char *source) override; 39 | Status SetStatePWM(float duty, const char *source) override { 40 | return Status::UNIMPLEMENTED(); 41 | }; 42 | Status Pulse(bool on, int duration_ms, const char *source) override { 43 | return Status::UNIMPLEMENTED(); 44 | }; 45 | void SetInvert(bool out_invert) override{}; 46 | int pin() const; 47 | 48 | protected: 49 | private: 50 | const int pin_; 51 | const int num_pixel_; 52 | 53 | bool value_; 54 | 55 | struct mgos_neopixel *pixel_; 56 | 57 | Output *chained_led_; 58 | 59 | const struct mgos_config_led *cfg_; 60 | 61 | StatusLED(const StatusLED &other) = delete; 62 | }; 63 | 64 | } // namespace shelly 65 | 66 | #endif -------------------------------------------------------------------------------- /src/shelly_switch.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "mgos_sys_config.h" 24 | #include "mgos_timers.hpp" 25 | 26 | #include "mgos_hap_chars.hpp" 27 | #include "mgos_hap_service.hpp" 28 | #include "shelly_common.hpp" 29 | #include "shelly_component.hpp" 30 | #include "shelly_input.hpp" 31 | #include "shelly_output.hpp" 32 | #include "shelly_pm.hpp" 33 | 34 | namespace shelly { 35 | 36 | // Common base for Switch, Outlet and Lock services. 37 | class ShellySwitch : public Component, public mgos::hap::Service { 38 | public: 39 | ShellySwitch(int id, Input *in, Output *out, PowerMeter *out_pm, 40 | Output *led_out, struct mgos_config_sw *cfg); 41 | virtual ~ShellySwitch(); 42 | 43 | // Component interface impl. 44 | Type type() const override; 45 | std::string name() const override; 46 | virtual Status Init() override; 47 | StatusOr GetInfo() const override; 48 | StatusOr GetInfoJSON() const override; 49 | Status SetConfig(const std::string &config_json, 50 | bool *restart_required) override; 51 | Status SetState(const std::string &state_json) override; 52 | bool IsIdle() override; 53 | 54 | bool GetOutputState() const; 55 | void SetOutputState(bool new_state, const char *source); 56 | 57 | // Additional input(s) are or'ed with the primary one. 58 | void AddInput(Input *in); 59 | 60 | protected: 61 | bool GetInputState() const; 62 | 63 | void InputEventHandler(Input::Event ev, bool state); 64 | 65 | void AutoOffTimerCB(); 66 | 67 | void SaveState(); 68 | 69 | std::vector ins_; 70 | Output *const out_; 71 | Output *const led_out_; 72 | PowerMeter *const out_pm_; 73 | struct mgos_config_sw *cfg_; 74 | 75 | std::vector in_handler_ids_; 76 | std::vector state_notify_chars_; 77 | 78 | mgos::Timer auto_off_timer_; 79 | bool dirty_ = false; 80 | 81 | ShellySwitch(const ShellySwitch &other) = delete; 82 | 83 | void AddPowerMeter(uint16_t *iid); 84 | void PowerMeterTimerCB(); 85 | mgos::Timer power_timer_; 86 | mgos::hap::Characteristic *power_char_ = nullptr; 87 | mgos::hap::Characteristic *total_power_char_ = nullptr; 88 | float last_power_ = 0.0f; 89 | float last_total_power_ = 0.0f; 90 | }; 91 | 92 | } // namespace shelly 93 | -------------------------------------------------------------------------------- /src/shelly_sys_led_btn.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | namespace shelly { 21 | 22 | void InitSysLED(int gpio, bool active_high); 23 | void CheckSysLED(); 24 | void InitSysBtn(int pin, bool on_value); 25 | 26 | } // namespace shelly 27 | -------------------------------------------------------------------------------- /src/shelly_temp_sensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_temp_sensor.hpp" 19 | 20 | namespace shelly { 21 | 22 | TempSensor::TempSensor() { 23 | } 24 | 25 | TempSensor::~TempSensor() { 26 | } 27 | 28 | void TempSensor::SetNotifier(Notifier notifier) { 29 | notifier_ = notifier; 30 | } 31 | 32 | void HumidityTempSensor::SetNotifierHumidity(Notifier notifier) { 33 | notifier_hum_ = notifier; 34 | } 35 | 36 | } // namespace shelly 37 | -------------------------------------------------------------------------------- /src/shelly_temp_sensor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_common.hpp" 21 | 22 | namespace shelly { 23 | 24 | typedef enum { 25 | TS = 0, 26 | TS_HUM, 27 | } TempType; 28 | 29 | class TempSensor { 30 | public: 31 | typedef std::function Notifier; 32 | 33 | TempSensor(); 34 | virtual ~TempSensor(); 35 | TempSensor(const TempSensor &other) = delete; 36 | 37 | virtual Status Init() = 0; 38 | 39 | virtual StatusOr GetTemperature() = 0; 40 | 41 | virtual void StartUpdating(int interval UNUSED_ARG) { 42 | } 43 | 44 | virtual void StopUpdating() { 45 | } 46 | 47 | virtual TempType getType() { 48 | return TS; 49 | } 50 | 51 | void SetNotifier(Notifier notifier); 52 | 53 | protected: 54 | Notifier notifier_; 55 | }; 56 | 57 | class HumidityTempSensor : public TempSensor { 58 | public: 59 | virtual StatusOr GetHumidity() = 0; 60 | void SetNotifierHumidity(Notifier notifier); 61 | TempType getType() { 62 | return TS_HUM; 63 | } 64 | 65 | protected: 66 | Notifier notifier_hum_; 67 | }; 68 | 69 | } // namespace shelly 70 | -------------------------------------------------------------------------------- /src/shelly_temp_sensor_ntc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_temp_sensor_ntc.hpp" 19 | 20 | #ifdef MGOS_HAVE_ADC 21 | 22 | #include 23 | 24 | #include "mgos_adc.h" 25 | 26 | #define ADC_RESOLUTION 1024.0f 27 | 28 | namespace shelly { 29 | 30 | NTCTempSensor::NTCTempSensor(int adc_channel, float vin, float rd) 31 | : adc_channel_(adc_channel), vin_(vin), rd_(rd) { 32 | } 33 | 34 | Status NTCTempSensor::Init() { 35 | if (!mgos_adc_enable(adc_channel_)) { 36 | return mgos::Errorf(STATUS_UNAVAILABLE, "failed to enable ADC channel %d", 37 | adc_channel_); 38 | } 39 | return Status::OK(); 40 | } 41 | 42 | NTCTempSensor::~NTCTempSensor() { 43 | } 44 | 45 | StatusOr NTCTempSensor::GetTemperature() { 46 | int raw = mgos_adc_read(adc_channel_); 47 | float v_out = raw / ADC_RESOLUTION; 48 | float rt = (v_out * rd_) / (vin_ - v_out); 49 | float t = Interpolate(rt); 50 | LOG(LL_DEBUG, 51 | ("NTC readings: %d, v_out %.3f rt %.3f t %.3f", raw, v_out, rt, t)); 52 | return t; 53 | } 54 | 55 | float NTCTempSensor::Interpolate(float rt) { 56 | float t; 57 | const CurveDataPoint *e1 = GetCurve(), *e2 = e1; 58 | do { 59 | if (rt >= e2->r) break; 60 | e1 = e2; 61 | e2++; 62 | if (e2->r == 0) e2--; 63 | } while (e1 != e2); 64 | if (e1 != e2) { 65 | // log10 interpolation. 66 | float f = log10f(rt / e2->r) / log10f(e1->r / e2->r); 67 | t = e2->t - (e2->t - e1->t) * f; 68 | } else { 69 | t = e1->t; 70 | } 71 | // LOG(LL_INFO, ("rt %.3f e1 %.3f:%.3f e2 %.3f:%.3f t %.3f", rt, e1->r, e1->t, 72 | // e2->r, e2->t, t)); 73 | return t; 74 | } 75 | 76 | TempSensorSDNT1608X103F3950::TempSensorSDNT1608X103F3950(int adc_channel, 77 | float vin, float rd) 78 | : NTCTempSensor(adc_channel, vin, rd) { 79 | } 80 | 81 | TempSensorSDNT1608X103F3950 ::~TempSensorSDNT1608X103F3950() { 82 | } 83 | 84 | const NTCTempSensor::CurveDataPoint *TempSensorSDNT1608X103F3950::GetCurve() { 85 | // clang-format off 86 | static const CurveDataPoint s_SDNT1608X103F3950_curve[] = { 87 | {300000, -36.5}, 88 | {200000, -31.0}, 89 | {100000, -19.5}, 90 | {90000, -18.0}, 91 | {80000, -16.0}, 92 | {70000, -14.0}, 93 | {60000, -11.0}, 94 | {50000, -7.5}, 95 | {40000, -3.5}, 96 | {30000, 2.0}, 97 | {20000, 10.5}, 98 | {10000, 25.0}, 99 | {9000, 27.5}, 100 | {8000, 30.0}, 101 | {7000, 33.5}, 102 | {6000, 37.0}, 103 | {5000, 41.5}, 104 | {4000, 46.5}, 105 | {3000, 55.0}, 106 | {2000, 66.0}, 107 | {1000, 87.0}, 108 | {900, 90.0}, 109 | {800, 94.0}, 110 | {700, 99.0}, 111 | {600, 104.0}, 112 | {500, 111.0}, 113 | {400, 114.5}, 114 | {340, 120.0}, 115 | {0, 0}, 116 | }; 117 | // clang-format on 118 | return s_SDNT1608X103F3950_curve; 119 | } 120 | 121 | } // namespace shelly 122 | 123 | #endif // MGOS_HAVE_ADC 124 | -------------------------------------------------------------------------------- /src/shelly_temp_sensor_ntc.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "shelly_temp_sensor.hpp" 21 | 22 | namespace shelly { 23 | 24 | class NTCTempSensor : public TempSensor { 25 | public: 26 | NTCTempSensor(int adc_channel, float vin, float rd); 27 | virtual ~NTCTempSensor(); 28 | 29 | Status Init() override; 30 | StatusOr GetTemperature() override; 31 | 32 | protected: 33 | struct CurveDataPoint { 34 | float r; // Ohm 35 | float t; // Celsius 36 | }; 37 | 38 | virtual const CurveDataPoint *GetCurve() = 0; 39 | 40 | float Interpolate(float rt); 41 | 42 | private: 43 | const int adc_channel_; 44 | const float vin_, rd_; 45 | }; 46 | 47 | class TempSensorSDNT1608X103F3950 : public NTCTempSensor { 48 | public: 49 | TempSensorSDNT1608X103F3950(int adc_channel, float vin, float rd); 50 | virtual ~TempSensorSDNT1608X103F3950(); 51 | 52 | protected: 53 | virtual const CurveDataPoint *GetCurve() override; 54 | }; 55 | 56 | } // namespace shelly 57 | -------------------------------------------------------------------------------- /src/shelly_white_controller.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_white_controller.hpp" 19 | 20 | #include "mgos.hpp" 21 | 22 | namespace shelly { 23 | 24 | WhiteController::WhiteController(struct mgos_config_lb *cfg, Output *out_w) 25 | : LightBulbController(cfg), out_w_(out_w) { 26 | } 27 | 28 | WhiteController::~WhiteController() { 29 | } 30 | 31 | StateW WhiteController::ConfigToState(const struct mgos_config_lb &cfg) const { 32 | StateW st; 33 | st.w = (cfg.state ? cfg.brightness / 100.0f : 0.0f); 34 | return st; 35 | } 36 | 37 | void WhiteController::ReportTransition(const StateW &next, const StateW &prev) { 38 | LOG(LL_INFO, ("Output 1: %.2f => %.2f", prev.w, next.w)); 39 | } 40 | 41 | void WhiteController::UpdatePWM(const StateW &state) { 42 | out_w_->SetStatePWM(state.w, "transition"); 43 | } 44 | 45 | std::string StateW::ToString() const { 46 | return mgos::SPrintf("[w=%.2f]", w); 47 | } 48 | 49 | } // namespace shelly 50 | -------------------------------------------------------------------------------- /src/shelly_white_controller.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "mgos_timers.hpp" 21 | 22 | #include "shelly_light_bulb_controller.hpp" 23 | #include "shelly_output.hpp" 24 | 25 | namespace shelly { 26 | 27 | struct StateW { 28 | float w; 29 | 30 | StateW operator+(const StateW &other) const { 31 | return {.w = w + other.w}; 32 | } 33 | 34 | StateW operator*(float a) const { 35 | return {.w = a * w}; 36 | } 37 | 38 | std::string ToString() const; 39 | }; 40 | 41 | class WhiteController : public LightBulbController { 42 | public: 43 | WhiteController(struct mgos_config_lb *cfg, Output *out_w); 44 | WhiteController(const WhiteController &other) = delete; 45 | ~WhiteController() final; 46 | 47 | BulbType Type() final { 48 | return BulbType::kWhite; 49 | } 50 | 51 | private: 52 | Output *const out_w_; 53 | 54 | StateW ConfigToState(const struct mgos_config_lb &cfg) const final; 55 | void ReportTransition(const StateW &prev, const StateW &next) final; 56 | void UpdatePWM(const StateW &state) final; 57 | }; 58 | } // namespace shelly 59 | -------------------------------------------------------------------------------- /src/shelly_wifi_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "shelly_wifi_config.hpp" 19 | 20 | #include "mgos.hpp" 21 | 22 | namespace shelly { 23 | 24 | bool WifiAPConfig::operator==(const WifiAPConfig &other) const { 25 | return (enable == other.enable && ssid == other.ssid && pass == other.pass); 26 | } 27 | 28 | bool WifiSTAConfig::operator==(const WifiSTAConfig &other) const { 29 | return (enable == other.enable && ssid == other.ssid && pass == other.pass && 30 | ip == other.ip && netmask == other.netmask && gw == other.gw && 31 | nameserver == other.nameserver); 32 | } 33 | 34 | std::string ScreenPassword(const std::string &pw) { 35 | std::string spw(pw); 36 | for (auto it = spw.begin(); it != spw.end(); it++) { 37 | *it = '*'; 38 | } 39 | return spw; 40 | } 41 | 42 | std::string WifiConfig::ToJSON() const { 43 | std::string ap_pw = ScreenPassword(ap.pass); 44 | std::string sta_pw = ScreenPassword(sta.pass); 45 | std::string sta1_pw = ScreenPassword(sta1.pass); 46 | return mgos::JSONPrintStringf( 47 | "{ap: {enable: %B, ssid: %Q, pass: %Q}, " 48 | "sta: {enable: %B, ssid: %Q, pass: %Q, ip: %Q, netmask: %Q, gw: %Q, " 49 | "nameserver: %Q}, " 50 | "sta1: {enable: %B, ssid: %Q, pass: %Q, ip: %Q, netmask: %Q, gw: %Q, " 51 | "nameserver: %Q}, " 52 | "sta_ps_mode: %d}", 53 | ap.enable, ap.ssid.c_str(), ap_pw.c_str(), sta.enable, sta.ssid.c_str(), 54 | sta_pw.c_str(), sta.ip.c_str(), sta.netmask.c_str(), sta.gw.c_str(), 55 | sta.nameserver.c_str(), sta1.enable, sta1.ssid.c_str(), sta1_pw.c_str(), 56 | sta1.ip.c_str(), sta1.netmask.c_str(), sta1.gw.c_str(), 57 | sta1.nameserver.c_str(), sta_ps_mode); 58 | } 59 | 60 | std::string FormatMACAddr(const uint8_t *mac, bool delims) { 61 | return (delims ? mgos::SPrintf("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], 62 | mac[1], mac[2], mac[3], mac[4], mac[5]) 63 | : mgos::SPrintf("%02x%02x%02x%02x%02x%02x", mac[0], mac[1], 64 | mac[2], mac[3], mac[4], mac[5])); 65 | } 66 | 67 | } // namespace shelly 68 | -------------------------------------------------------------------------------- /src/shelly_wifi_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "shelly_common.hpp" 23 | 24 | namespace shelly { 25 | 26 | struct WifiAPConfig { 27 | bool enable = false; 28 | std::string ssid; 29 | std::string pass; 30 | 31 | bool operator==(const WifiAPConfig &other) const; 32 | }; 33 | 34 | struct WifiSTAConfig { 35 | bool enable = false; 36 | std::string ssid; 37 | std::string pass; 38 | std::string ip; 39 | std::string netmask; 40 | std::string gw; 41 | std::string nameserver; 42 | 43 | bool operator==(const WifiSTAConfig &other) const; 44 | }; 45 | 46 | struct WifiConfig { 47 | WifiAPConfig ap; 48 | WifiSTAConfig sta; 49 | WifiSTAConfig sta1; 50 | int sta_ps_mode = 0; 51 | 52 | std::string ToJSON() const; 53 | }; 54 | 55 | WifiConfig GetWifiConfig(); 56 | 57 | Status SetWifiConfig(const WifiConfig &cfg); 58 | 59 | void ResetWifiConfig(); 60 | 61 | struct WifiInfo { 62 | bool ap_running = false; 63 | bool sta_connecting = false; 64 | bool sta_connected = false; 65 | std::string status; 66 | // When connected: 67 | int sta_rssi = 0; 68 | std::string sta_ip; 69 | std::string sta_ssid; 70 | }; 71 | 72 | WifiInfo GetWifiInfo(); 73 | 74 | void ReportClientRequest(const std::string &client_addr); 75 | 76 | std::string ScreenPassword(const std::string &pw); 77 | 78 | void InitWifiConfigManager(); 79 | 80 | void StartWifiConfigManager(); 81 | 82 | std::string GetMACAddr(bool sta = true, bool delims = true); 83 | 84 | std::string FormatMACAddr(const uint8_t *mac, bool delims); 85 | 86 | } // namespace shelly 87 | -------------------------------------------------------------------------------- /tools/shelly_update_server/.gitignore: -------------------------------------------------------------------------------- 1 | shelly_update_server 2 | -------------------------------------------------------------------------------- /tools/shelly_update_server/README.md: -------------------------------------------------------------------------------- 1 | # Shelly-HomeKit Update Server 2 | 3 | ## Overview 4 | 5 | This server is intended as a single entry point for all update requests and will contain 6 | the logic for serving the right update based on what the device is currently running. 7 | 8 | Initial version will handle stock -> HomeKit upgrades but eventually HK update logic will be moved here as well, 9 | replacing the current JSON + version regex matching done in UI. 10 | 11 | ## Running 12 | 13 | `go build -v && ./shelly_update_server --listen-addr=:8080 --stock-model-map=stock_model_map.yml` 14 | 15 | ## Endpoints 16 | 17 | * `/update` - this is the main entry point for all device updates, wille xamine headers and will redirect to the actual ZIP file to update from (according to model and location template from `--dest-url-template`. 18 | * `/log` - will show recent history of requests from this address, for debugging. 19 | -------------------------------------------------------------------------------- /tools/shelly_update_server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mongoose-os-apps/shelly-homekit/tools/shelly_update_server 2 | 3 | go 1.13 4 | 5 | require gopkg.in/yaml.v3 v3.0.1 6 | -------------------------------------------------------------------------------- /tools/shelly_update_server/go.sum: -------------------------------------------------------------------------------- 1 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 2 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 3 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 4 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 5 | -------------------------------------------------------------------------------- /tools/shelly_update_server/parse_log.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Shelly-HomeKit Contributors 3 | * All rights reserved 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package main 19 | 20 | import ( 21 | "bufio" 22 | "log" 23 | "os" 24 | "strings" 25 | ) 26 | 27 | func parseLog(fname string, stockModelMap *StockModelMap) { 28 | file, err := os.Open(fname) 29 | if err != nil { 30 | log.Fatal(err) 31 | } 32 | defer file.Close() 33 | 34 | numUnsupported := 0 35 | scanner := bufio.NewScanner(file) 36 | for scanner.Scan() { 37 | parts := strings.Split(scanner.Text(), ` "`) 38 | mgosFWVersion := strings.Trim(parts[len(parts)-2], `"`) 39 | mgosDeviceID := strings.Trim(parts[len(parts)-1], `"`) 40 | hkModel, err := stockModelMap.GetHomeKitModel(mgosFWVersion, mgosDeviceID) 41 | if err != nil { 42 | log.Printf("%s", err) 43 | numUnsupported++ 44 | } 45 | if false { 46 | log.Printf("line: %s|%s -> %s", mgosFWVersion, mgosDeviceID, hkModel) 47 | } 48 | } 49 | 50 | if err := scanner.Err(); err != nil { 51 | log.Fatal(err) 52 | } 53 | 54 | log.Printf("Unsupported : %d", numUnsupported) 55 | } 56 | -------------------------------------------------------------------------------- /tools/shelly_update_server/stock_model_map.yml: -------------------------------------------------------------------------------- 1 | # Map of stock device id prefix -> shelly-homekit model. 2 | # Used by the update redirector. 3 | models: 4 | shelly1: Shelly1 5 | shelly1l: Shelly1L 6 | shelly1pm: Shelly1PM 7 | ShellyBulbDuo: ShellyDuo 8 | shellycolorbulb: ShellyColorBulb 9 | shellyix3: ShellyI3 10 | shellyplug: ShellyPlug 11 | shellyplug-s: ShellyPlugS 12 | shellyplus1: ShellyPlus1 13 | ShellyPlus1: ShellyPlus1 14 | shellyplus1pm: ShellyPlus1PM 15 | ShellyPlus1PM: ShellyPlus1PM 16 | shellyplus2pm: ShellyPlus2PM 17 | ShellyPlus2PM: ShellyPlus2PM 18 | shellyplusi4: ShellyPlusI4 19 | ShellyPlusI4: ShellyPlusI4 20 | shellyplusplug-s: ShellyPlusPlugS 21 | shellyplusplugs: ShellyPlusPlugS 22 | shellyrgbw2: ShellyRGBW2 23 | shellyswitch: Shelly2 24 | shellyswitch25: Shelly25 25 | shellyuni: ShellyUNI 26 | ShellyVintage: ShellyVintage 27 | ShellyPlus1Mini: ShellyPlus1Mini 28 | ShellyMini1G3: ShellyMini1Gen3 29 | ShellyMini1PMG3: ShellyMini1PMGen3 30 | ShellyPlusRGBWPM: ShellyPlusRGBWPM 31 | 32 | # Known unsupported models. 33 | shellybulb: x 34 | shellybutton1: x 35 | shellydimmer: x 36 | shellydimmer2: x 37 | shellydw2: x 38 | shellyem: x 39 | shellyem3: x 40 | shellyflood: x 41 | shellygas: x 42 | shellyht: x 43 | shellyplugu1: x 44 | shellyplugus: x 45 | shellypro1: x 46 | shellypro1pm: x 47 | shellypro2: x 48 | shellypro4pm: x 49 | --------------------------------------------------------------------------------