Jump to content

SENSBLUE ATLAS/Home Assistant: Difference between revisions

No edit summary
 
(43 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{DISPLAYTITLE:Home Assistant}}
{{DISPLAYTITLE:Home Assistant}}[[File:Home Assistant Logo.png|frameless|150x150px]]
 
== Fast installation script ==
(If you are feeling lazy)
<table style="border: none; background: transparent; margin: 15px 0; border-collapse: collapse;">
    <td style="padding: 0 0 0 10px; border: none; background: transparent;">
        <span class="atlas-btn">[[Media:Atlas-ha-install-v1.zip|Download Script]]</span>
    </td>
</table>This script takes a backup file as an argument and contains: <code>.tar.gz</code> <syntaxhighlight lang="bash">
atlas-ha-installer/
├── docker-compose.yml
├── install.sh
├── README.md
├── provision_areas.py
└── ha-config/
    ├── configuration.yaml
    ├── mqtt.yaml
    ├── automations.yaml
    ├── scripts.yaml
    └── scenes.yaml
</syntaxhighlight>
 
=== 1. What the script does ===
{| class="wikitable mix-table"
!Stage
!Action
|-
|Validates argument
|Confirms that a backup file was specified
|-
|Installs dependencies
|Run <code>apt update</code> and install <code>docker.io</code> and <code>docker-compose-plugin</code>
|-
|Enables Docker
|Executes <code>systemctl enable docker</code> and <code>systemctl start docker</code>
|-
|Breed pasta
|Ensure <code>/opt/atlas-ha</code> exists
|-
|Extract backup
|Extract the <code>.tar.gz</code> file to <code>/opt/atlas-ha</code>
|-
|HA starts up
|Navigates to <code>/opt/atlas-ha</code> and runs <code>sudo docker compose up -d</code>
|-
|Show URL
|Indicate access via <code><nowiki>http://DEVICE_IP:8123</nowiki></code>
|}
 
=== 2. Prepare Device ===
Transfer the package to ATLAS, for example using WinSCP:
 
# Open the connection to ATLAS using WinSCP.
# Copy <code>atlas-ha-installer.zip</code> or <code>atlas-ha-installer.tar.gz</code> to <code>/home/pi</code>.
# Drag the folder extracted from the .zip file to the /home/pi directory on ATLAS.
 
'''Note:''' If you need help installing WinSCP, '''''<u>[[SENSBLUE ATLAS/Putty & WinSCP#Install WinSCP|click here]]</u>'''''.
 
On ATLAS, after transferring the necessary files, establish an SSH connection
 
If the package is <code>.zip</code>:<syntaxhighlight lang="bash">
cd /home/pi
unzip atlas-ha-installer.zip
cd atlas-ha-installer
</syntaxhighlight>If the package is:<code>.tar.gz</code><syntaxhighlight lang="bash">cd /home/pi tar
-xzf atlas-ha-installer.tar.gz
cd atlas-ha-installer</syntaxhighlight>Grant execution permission<syntaxhighlight lang="bash">
chmod +x install.sh
</syntaxhighlight>
 
=== 3. Execute installation ===
The script will install the required dependencies, install/configure Docker, copy the files to <code>/opt/atlas-ha</code>, and start Home Assistant.<syntaxhighlight lang="bash">
sudo ./install.sh
</syntaxhighlight>After installation, the following should exist:<syntaxhighlight>
/opt/atlas-ha/
├── docker-compose.yml
└── ha-config/
    ├── configuration.yaml
    ├── mqtt.yaml
    ├── automations.yaml
    ├── scripts.yaml
    └── scenes.yaml
</syntaxhighlight>
 
=== 4. Post-script validation ===
Verify that the container is active:<syntaxhighlight lang="bash">
sudo docker ps
</syntaxhighlight>Check logs:<syntaxhighlight lang="bash">
sudo docker logs -f homeassistant
</syntaxhighlight>Verify HTTP response:<syntaxhighlight lang="bash">
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8123
</syntaxhighlight>Expected result:
{| class="wikitable mix-table"
!Code
!Meaning
|-
|200
|Home Assistant access
|-
|302
|Home Assistant accessible, with redirection
|-
|000 or connection refused
|It can be normal for the first 1–2 minutes; wait and repeat.
|}Access in browser<syntaxhighlight>
http://<ip-do-atlas>:8123
</syntaxhighlight>
 
= Home Assistant integration =
= Home Assistant integration =
'''Installing Home Assistant on the SENSBLUE ATLAS / i.Cee²'''
'''Installing Home Assistant on the SENSBLUE ATLAS'''


'''Objective'''
'''Objective'''
Line 22: Line 129:
|-
|-
|Device
|Device
|SENSBLUE ATLAS / i.Cee²
|SENSBLUE ATLAS
|-
|-
|Platform
|Platform
Line 45: Line 152:
|Local Mosquitto on 127.0.0.1:1883
|Local Mosquitto on 127.0.0.1:1883
|}
|}
Check the system:<syntaxhighlight lang="bash">cat /etc/os-release | grep PRETTY_NAME
To locate the IP address of the ATLAS device, '''toggle the joystick to the right''' to navigate to the '''<nowiki/>'Network'''' screen, where the '''eth1''' address is displayed.
 
 
[[File:Front Screen.svg|center|frameless|566x566px]]
 
 
 
Once your preferred terminal application (e.g., PuTTY) is installed, initiate an SSH session using the ATLAS IP address and execute the following command to verify the system:
 
'''Note:''' If you need help installing PuTTY, [[SENSBLUE ATLAS/Putty & WinSCP#Install PuTTY|'''''<u>click here</u>''''']].
[[File:Image.png|center|frameless|448x448px]]
 
'''Note:''' SSH access to the ATLAS device requires authentication.
 
* '''Username:''' pi
* '''Password:''' atlas2026
<syntaxhighlight lang="bash">cat /etc/os-release | grep PRETTY_NAME
uname -m
uname -m
df -h /</syntaxhighlight>
df -h /</syntaxhighlight>'''Expected output:'''<syntaxhighlight lang="bash">
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
aarch64
Filesystem      Size  Used Avail Use% Mounted on
/dev/mmcblk0p2  29G  5.5G  23G  20% /
</syntaxhighlight>


=== 2. Ports used on ATLAS ===
=== 2. Ports used on ATLAS ===
Line 70: Line 198:
|8123
|8123
|}
|}
Check the stack's ports:<syntaxhighlight lang="bash">
'''Check the stack's ports:'''<syntaxhighlight lang="bash">
for p in 1880 1883 3000 8086; do
for p in 1880 1883 3000 8086; do
ss -tlnp | grep ":$p " && echo "port $p OK"
ss -tlnp | grep ":$p " && echo "port $p OK"
done
done
</syntaxhighlight>'''Expected output:'''<syntaxhighlight lang="bash">
LISTEN 0      511          0.0.0.0:1880      0.0.0.0:*    users:(("node-red",pid=614,fd=19))
porta 1880 OK
LISTEN 0      100          0.0.0.0:1883      0.0.0.0:*                                   
LISTEN 0      100            [::]:1883          [::]:*                                   
porta 1883 OK
LISTEN 0      4096              *:3000            *:*                                   
porta 3000 OK
LISTEN 0      4096              *:8086            *:* 
porta 8086 OK                                 
</syntaxhighlight>
</syntaxhighlight>


Line 88: Line 226:
# Test with hello-world.
# Test with hello-world.


==== 3.1 Update packages ====
<syntaxhighlight lang="bash">
sudo apt-get update
</syntaxhighlight>
==== 3.2 Install dependencies ====
<syntaxhighlight lang="bash">
sudo apt-get install -y ca-certificate curl
sudo install -m 0755 -d /etc/apt/keyrings
</syntaxhighlight>
==== 3.3 Add Docker GPG key ====
<syntaxhighlight lang="bash">
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
</syntaxhighlight>
==== 3.4 Add Docker repository ====
<syntaxhighlight lang="bash">
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \ https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
</syntaxhighlight>
==== 3.5 Install Docker Engine and Docker Compose plugin ====
<syntaxhighlight lang="bash">
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
</syntaxhighlight>


Check that Docker is operational:<syntaxhighlight lang="bash">
==== 3.6 Verify if Docker is operational ====
<syntaxhighlight lang="bash">
sudo docker run --rm hello-world
sudo docker run --rm hello-world
</syntaxhighlight>If <code>apt-get update</code> returns a 404 error for the Docker repository, temporarily use the bookworm line for the Docker repository and repeat the update/installation.
</syntaxhighlight>


Example alternative line:<syntaxhighlight lang="bash">deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable</syntaxhighlight>
==== '''Note on Debian 13 (Trixie)''' ====
If <code>apt-get update</code> returns a <code>404</code> error for the Docker repository on <code>trixie</code>, temporarily use <code>bookworm</code> in the Docker repository line and re-run the update/installation.
 
Example of the alternative line:<syntaxhighlight lang="bash">deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable</syntaxhighlight>


=== 4. Create the Home Assistant project ===
=== 4. Create the Home Assistant project ===
Line 187: Line 359:
Configure the broker as:
Configure the broker as:


'''127.0.0.1:1883'''
'''127.0.0.1'''


After adding the MQTT integration, create the following YAML files to declare the entities used in the current installation.
After adding the MQTT integration, create the following YAML files to declare the entities used in the current installation.
Line 214: Line 386:


sudo tee mqtt.yaml > /dev/null << 'EOF'
sudo tee mqtt.yaml > /dev/null << 'EOF'
sensor:
sensor:
   - name: "ATLAS AI1"
   - name: "ATLAS AI1"
     unique_id: atlas_ai1
     unique_id: atlas_ai1
     state_topic: "analogInputs/runtime/out"
     state_topic: "analogInputs/runtime/out"
     value_template: "{{ value_json.task.taskResult.AI1.result | float(0) }}"
     value_template: "{{ value_json.task.taskResult.AI1.result }}"
     unit_of_measurement: "V"
     unit_of_measurement: "V"
     device_class: voltage
     device_class: voltage
Line 226: Line 399:
     unique_id: atlas_ai2
     unique_id: atlas_ai2
     state_topic: "analogInputs/runtime/out"
     state_topic: "analogInputs/runtime/out"
     value_template: "{{ value_json.task.taskResult.AI2.result | float(0) }}"
     value_template: "{{ value_json.task.taskResult.AI2.result }}"
     unit_of_measurement: "V"
     unit_of_measurement: "V"
     device_class: voltage
     device_class: voltage
Line 234: Line 407:
     unique_id: atlas_ai3
     unique_id: atlas_ai3
     state_topic: "analogInputs/runtime/out"
     state_topic: "analogInputs/runtime/out"
     value_template: "{{ value_json.task.taskResult.AI3.result | float(0) }}"
     value_template: "{{ value_json.task.taskResult.AI3.result }}"
     unit_of_measurement: "V"
     unit_of_measurement: "V"
     device_class: voltage
     device_class: voltage
Line 242: Line 415:
     unique_id: atlas_ai4
     unique_id: atlas_ai4
     state_topic: "analogInputs/runtime/out"
     state_topic: "analogInputs/runtime/out"
     value_template: "{{ value_json.task.taskResult.AI4.result | float(0) }}"
     value_template: "{{ value_json.task.taskResult.AI4.result }}"
     unit_of_measurement: "V"
     unit_of_measurement: "V"
     device_class: voltage
     device_class: voltage
     state_class: measurement
     state_class: measurement
  - name: "ATLAS CPU Usage"
    unique_id: atlas_cpu_usage
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.cpu_percent }}"
    unit_of_measurement: "%"
    device_class: power_factor
    state_class: measurement
  - name: "ATLAS CPU Temperature"
    unique_id: atlas_cpu_temperature
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.cpu_tempC }}"
    unit_of_measurement: "°C"
    device_class: temperature
    state_class: measurement
  - name: "ATLAS CPU0 Frequency"
    unique_id: atlas_cpu0_frequency
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.cpu_freqs.cpu0.frequency_mhz }}"
    unit_of_measurement: "MHz"
    state_class: measurement
  - name: "ATLAS CPU1 Frequency"
    unique_id: atlas_cpu1_frequency
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.cpu_freqs.cpu1.frequency_mhz }}"
    unit_of_measurement: "MHz"
    state_class: measurement
  - name: "ATLAS CPU2 Frequency"
    unique_id: atlas_cpu2_frequency
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.cpu_freqs.cpu2.frequency_mhz }}"
    unit_of_measurement: "MHz"
    state_class: measurement
  - name: "ATLAS CPU3 Frequency"
    unique_id: atlas_cpu3_frequency
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.cpu_freqs.cpu3.frequency_mhz }}"
    unit_of_measurement: "MHz"
    state_class: measurement
  - name: "ATLAS CPU Throttle"
    unique_id: atlas_cpu_throttle
    state_topic: "systemHealth/runtime/out"
    value_template: >
      {% if value_json.task.taskResult.cpu_throttle == "0x0" %}
        No
      {% else %}
        Yes
      {% endif %}
  - name: "ATLAS RAM Usage"
    unique_id: atlas_ram_usage
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.ram_percent }}"
    unit_of_measurement: "%"
    state_class: measurement
  - name: "ATLAS RAM Total"
    unique_id: atlas_ram_total
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.ram_total_mb }}"
    unit_of_measurement: "GB"
    state_class: measurement
  - name: "ATLAS RAM Used"
    unique_id: atlas_ram_used
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.ram_used_mb }}"
    unit_of_measurement: "GB"
    state_class: measurement
  - name: "ATLAS RAM Available"
    unique_id: atlas_ram_available
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.ram_available_mb }}"
    unit_of_measurement: "GB"
    state_class: measurement
  - name: "ATLAS Disk Usage"
    unique_id: atlas_disk_usage
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.disk_percent }}"
    unit_of_measurement: "%"
    state_class: measurement
  - name: "ATLAS Disk Total"
    unique_id: atlas_disk_total
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.disk_total_gb }}"
    unit_of_measurement: "GB"
    device_class: data_size
    state_class: measurement
  - name: "ATLAS Disk Used"
    unique_id: atlas_disk_used
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.disk_used_gb }}"
    unit_of_measurement: "GB"
    device_class: data_size
    state_class: measurement
  - name: "ATLAS Disk Free"
    unique_id: atlas_disk_free
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.disk_free_gb }}"
    unit_of_measurement: "GB"
    device_class: data_size
    state_class: measurement
  - name: "ATLAS eMMC RUL State"
    unique_id: atlas_emmc_rul_state
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.emmc_rul.state }}"
  - name: "ATLAS eMMC RUL Reason"
    unique_id: atlas_emmc_rul_reason
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.emmc_rul.reason }}"
  - name: "ATLAS Uptime"
    unique_id: atlas_uptime_seconds
    state_topic: "systemHealth/runtime/out"
    value_template: "{{ value_json.task.taskResult.uptime_sec }}"
    unit_of_measurement: "s"
    device_class: duration
    state_class: measurement


binary_sensor:
binary_sensor:
Line 251: Line 557:
     unique_id: atlas_di1
     unique_id: atlas_di1
     state_topic: "digitalInputs/runtime/out"
     state_topic: "digitalInputs/runtime/out"
     value_template: >-
     value_template: >
       {% set di = value_json.task.taskResult.DI1 %}
       {% if value_json.task.taskResult.DI1.result == true %}
      {% if di.result is defined %}
         ON
         {{ 'ON' if di.result == true else 'OFF' }}
       {% else %}
       {% else %}
         {{ 'ON' if di.state == 'high' else 'OFF' }}
         OFF
       {% endif %}
       {% endif %}
     payload_on: "ON"
     payload_on: "ON"
Line 264: Line 569:
     unique_id: atlas_di2
     unique_id: atlas_di2
     state_topic: "digitalInputs/runtime/out"
     state_topic: "digitalInputs/runtime/out"
     value_template: >-
     value_template: >
       {% set di = value_json.task.taskResult.DI2 %}
       {% if value_json.task.taskResult.DI2.result == true %}
      {% if di.result is defined %}
         ON
         {{ 'ON' if di.result == true else 'OFF' }}
       {% else %}
       {% else %}
         {{ 'ON' if di.state == 'high' else 'OFF' }}
         OFF
       {% endif %}
       {% endif %}
     payload_on: "ON"
     payload_on: "ON"
Line 277: Line 581:
     unique_id: atlas_di3
     unique_id: atlas_di3
     state_topic: "digitalInputs/runtime/out"
     state_topic: "digitalInputs/runtime/out"
     value_template: >-
     value_template: >
       {% set di = value_json.task.taskResult.DI3 %}
       {% if value_json.task.taskResult.DI3.result == true %}
      {% if di.result is defined %}
         ON
         {{ 'ON' if di.result == true else 'OFF' }}
       {% else %}
       {% else %}
         {{ 'ON' if di.state == 'high' else 'OFF' }}
         OFF
       {% endif %}
       {% endif %}
     payload_on: "ON"
     payload_on: "ON"
Line 290: Line 593:
     unique_id: atlas_di4
     unique_id: atlas_di4
     state_topic: "digitalInputs/runtime/out"
     state_topic: "digitalInputs/runtime/out"
     value_template: >-
     value_template: >
       {% set di = value_json.task.taskResult.DI4 %}
       {% if value_json.task.taskResult.DI4.result == true %}
      {% if di.result is defined %}
         ON
         {{ 'ON' if di.result == true else 'OFF' }}
       {% else %}
       {% else %}
         {{ 'ON' if di.state == 'high' else 'OFF' }}
         OFF
       {% endif %}
       {% endif %}
     payload_on: "ON"
     payload_on: "ON"
     payload_off: "OFF"
     payload_off: "OFF"
  - name: "ATLAS eMMC RUL OK"
    unique_id: atlas_emmc_rul_ok
    state_topic: "systemHealth/runtime/out"
    value_template: >
      {% if value_json.task.taskResult.emmc_rul.ok == true %}
        ON
      {% else %}
        OFF
      {% endif %}
    payload_on: "ON"
    payload_off: "OFF"
    device_class: problem
  - name: "ATLAS eMMC RUL Problem"
    unique_id: atlas_emmc_rul_problem
    state_topic: "systemHealth/runtime/out"
    value_template: >
      {% if value_json.task.taskResult.emmc_rul.ok == false %}
        ON
      {% else %}
        OFF
      {% endif %}
    payload_on: "ON"
    payload_off: "OFF"
    device_class: problem


switch:
switch:
   - name: "ATLAS DO1"
   - name: "ATLAS DO1"
     unique_id: atlas_do1
     unique_id: atlas_do1
    state_topic: "digitalOutputs/runtime/out"
     command_topic: "digitalOutputs/runtime/in"
     command_topic: "digitalOutputs/runtime/in"
     state_topic: "digitalOutputs/runtime/out"
     value_template: >
     payload_on: '{"id":0,"origin":"HA","task":{"action":"SET","taskParams":{"DO1":{"state":"high"}}}}'
      {% if value_json.task.taskResult.DO1.result == true %}
     payload_off: '{"id":0,"origin":"HA","task":{"action":"SET","taskParams":{"DO1":{"state":"low"}}}}'
        ON
    value_template: "{{ value_json.task.taskResult.DO1.state }}"
      {% else %}
     state_on: "high"
        OFF
     state_off: "low"
      {% endif %}
    optimistic: false
     payload_on: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO1":true}}}'
     payload_off: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO1":false}}}'
     state_on: "ON"
     state_off: "OFF"


   - name: "ATLAS DO2"
   - name: "ATLAS DO2"
     unique_id: atlas_do2
     unique_id: atlas_do2
    state_topic: "digitalOutputs/runtime/out"
     command_topic: "digitalOutputs/runtime/in"
     command_topic: "digitalOutputs/runtime/in"
     state_topic: "digitalOutputs/runtime/out"
     value_template: >
     payload_on: '{"id":0,"origin":"HA","task":{"action":"SET","taskParams":{"DO2":{"state":"high"}}}}'
      {% if value_json.task.taskResult.DO2.result == true %}
     payload_off: '{"id":0,"origin":"HA","task":{"action":"SET","taskParams":{"DO2":{"state":"low"}}}}'
        ON
    value_template: "{{ value_json.task.taskResult.DO2.state }}"
      {% else %}
     state_on: "high"
        OFF
     state_off: "low"
      {% endif %}
    optimistic: false
     payload_on: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO2":true}}}'
     payload_off: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO2":false}}}'
     state_on: "ON"
     state_off: "OFF"


   - name: "ATLAS DO3"
   - name: "ATLAS DO3"
     unique_id: atlas_do3
     unique_id: atlas_do3
    state_topic: "digitalOutputs/runtime/out"
     command_topic: "digitalOutputs/runtime/in"
     command_topic: "digitalOutputs/runtime/in"
     state_topic: "digitalOutputs/runtime/out"
     value_template: >
     payload_on: '{"id":0,"origin":"HA","task":{"action":"SET","taskParams":{"DO3":{"state":"high"}}}}'
      {% if value_json.task.taskResult.DO3.result == true %}
     payload_off: '{"id":0,"origin":"HA","task":{"action":"SET","taskParams":{"DO3":{"state":"low"}}}}'
        ON
    value_template: "{{ value_json.task.taskResult.DO3.state }}"
      {% else %}
     state_on: "high"
        OFF
     state_off: "low"
      {% endif %}
    optimistic: false
     payload_on: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO3":true}}}'
     payload_off: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO3":false}}}'
     state_on: "ON"
     state_off: "OFF"


   - name: "ATLAS DO4"
   - name: "ATLAS DO4"
     unique_id: atlas_do4
     unique_id: atlas_do4
    state_topic: "digitalOutputs/runtime/out"
     command_topic: "digitalOutputs/runtime/in"
     command_topic: "digitalOutputs/runtime/in"
    value_template: >
      {% if value_json.task.taskResult.DO4.result == true %}
        ON
      {% else %}
        OFF
      {% endif %}
    payload_on: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO4":true}}}'
    payload_off: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO4":false}}}'
    state_on: "ON"
    state_off: "OFF"
 
  - name: "ATLAS DO5"
    unique_id: atlas_do5
    state_topic: "digitalOutputs/runtime/out"
    command_topic: "digitalOutputs/runtime/in"
    value_template: >
      {% if value_json.task.taskResult.DO5.result == true %}
        ON
      {% else %}
        OFF
      {% endif %}
    payload_on: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO5":true}}}'
    payload_off: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO5":false}}}'
    state_on: "ON"
    state_off: "OFF"
  - name: "ATLAS DO6"
    unique_id: atlas_do6
    state_topic: "digitalOutputs/runtime/out"
    command_topic: "digitalOutputs/runtime/in"
    value_template: >
      {% if value_json.task.taskResult.DO6.result == true %}
        ON
      {% else %}
        OFF
      {% endif %}
    payload_on: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO6":true}}}'
    payload_off: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO6":false}}}'
    state_on: "ON"
    state_off: "OFF"
  - name: "ATLAS DO7"
    unique_id: atlas_do7
    state_topic: "digitalOutputs/runtime/out"
    command_topic: "digitalOutputs/runtime/in"
    value_template: >
      {% if value_json.task.taskResult.DO7.result == true %}
        ON
      {% else %}
        OFF
      {% endif %}
    payload_on: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO7":true}}}'
    payload_off: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO7":false}}}'
    state_on: "ON"
    state_off: "OFF"
  - name: "ATLAS DO8"
    unique_id: atlas_do8
     state_topic: "digitalOutputs/runtime/out"
     state_topic: "digitalOutputs/runtime/out"
     payload_on: '{"id":0,"origin":"HA","task":{"action":"SET","taskParams":{"DO4":{"state":"high"}}}}'
    command_topic: "digitalOutputs/runtime/in"
     payload_off: '{"id":0,"origin":"HA","task":{"action":"SET","taskParams":{"DO4":{"state":"low"}}}}'
    value_template: >
     value_template: "{{ value_json.task.taskResult.DO4.state }}"
      {% if value_json.task.taskResult.DO8.result == true %}
     state_on: "high"
        ON
     state_off: "low"
      {% else %}
     optimistic: false
        OFF
      {% endif %}
     payload_on: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO8":true}}}'
    payload_off: '{"origin":"HA","task":{"alias":"SET_DO","taskParams":{"DO8":false}}}'
     state_on: "ON"
    state_off: "OFF"
 
number:
  - name: "ATLAS AO1"
    unique_id: atlas_ao1
    state_topic: "analogOutputs/runtime/out"
    command_topic: "analogOutputs/runtime/in"
    value_template: "{{ value_json.task.taskResult.AO1.result }}"
    command_template: >
      {"origin":"HA","task":{"alias":"SET_AO","taskParams":{"AO1":{{ value | float }}}}}
    min: 4
    max: 20
    step: 0.1
    unit_of_measurement: "mA"
    mode: slider
 
  - name: "ATLAS AO2"
    unique_id: atlas_ao2
    state_topic: "analogOutputs/runtime/out"
    command_topic: "analogOutputs/runtime/in"
     value_template: "{{ value_json.task.taskResult.AO2.result }}"
     command_template: >
      {"origin":"HA","task":{"alias":"SET_AO","taskParams":{"AO2":{{ value | float }}}}}
    min: 4
     max: 20
    step: 0.1
    unit_of_measurement: "mA"
     mode: slider
EOF
EOF
</syntaxhighlight>'''Notes about this mqtt.yaml'''
</syntaxhighlight>'''Notes about this mqtt.yaml'''
Line 497: Line 928:
</syntaxhighlight>
</syntaxhighlight>


=== 15. Production notes ===
=== 15. Automatic installation with script ===
Before sending a unit to a client, review the following points:
{| class="wikitable mix-table"
!Point
!Note
|-
|MQTT Broker
|Mosquitto may be unauthenticated and listening on 0.0.0.0; secure before exposing the unit
|-
|Grafana
|Change default credentials, e.g., admin/admin
|-
|Access Point
|If ATLAS routes traffic via wlan0, validate FORWARD, DOCKER-USER, nftables rules and persistence
|-
|Initial HA account
|The admin account should not be the same on all units
|-
|Network
|Validate port exposure when the unit has a routable IP via Ethernet/LTE
|}
 
=== 16. Automatic installation with script ===
The current installation can be performed using the script:<syntaxhighlight lang="bash">
The current installation can be performed using the script:<syntaxhighlight lang="bash">
install-atlas-ha.sh
install-atlas-ha.sh
Line 526: Line 935:
</syntaxhighlight>
</syntaxhighlight>


==== 16.1 Script used ====
==== 15.1 Script used ====
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
#!/bin/bash
#!/bin/bash
Line 562: Line 971:
</syntaxhighlight>
</syntaxhighlight>


==== 16.2 What the script does ====
==== 15.2 What the script does ====
{| class="wikitable"
{| class="wikitable mix-table"
!Step
!Step
!Action
!Action
Line 589: Line 998:
|}
|}


==== 16.3 Prepare files ====
==== 15.3 Prepare files ====
Copy to ATLAS:<syntaxhighlight lang="bash">
Copy to ATLAS:<syntaxhighlight lang="bash">
install-atlas-ha.sh
install-atlas-ha.sh
Line 600: Line 1,009:
</syntaxhighlight>
</syntaxhighlight>


==== 16.4 Run installation ====
==== 15.4 Run installation ====
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
sudo ./install-atlas-ha.sh atlas-ha-backup.tar.gz
sudo ./install-atlas-ha.sh atlas-ha-backup.tar.gz
Line 607: Line 1,016:
</syntaxhighlight>
</syntaxhighlight>


==== 16.5 Expected backup structure ====
==== 15.5 Expected backup structure ====
The backup should contain the necessary structure so that, after extraction in <code>/opt/atlas-ha</code>, at least the following exists:
The backup should contain the necessary structure so that, after extraction in <code>/opt/atlas-ha</code>, at least the following exists:


Line 628: Line 1,037:
If the backup does not contain <code>docker-compose.yml</code>, the command <code>sudo docker compose up -d</code> will not be able to start Home Assistant.
If the backup does not contain <code>docker-compose.yml</code>, the command <code>sudo docker compose up -d</code> will not be able to start Home Assistant.


==== 16.6 Validation after the script ====
==== 15.6 Validation after the script ====
Check if the container is active:<syntaxhighlight lang="bash">
Check if the container is active:<syntaxhighlight lang="bash">
sudo docker ps
sudo docker ps
Line 637: Line 1,046:
" http://localhost:8123
" http://localhost:8123
</syntaxhighlight>'''Expected result:'''
</syntaxhighlight>'''Expected result:'''
{| class="wikitable"
{| class="wikitable mix-table"
!Code
!Code
!Meaning
!Meaning
Line 654: Line 1,063:
http://&#x3C;atlas-ip&#x3E;:8123
http://&#x3C;atlas-ip&#x3E;:8123


=== 17. Uninstall / revert ===
=== 16. Uninstall / revert ===
Stop and remove the container:<syntaxhighlight lang="bash">
Stop and remove the container:<syntaxhighlight lang="bash">
cd /opt/atlas-ha
cd /opt/atlas-ha
Line 664: Line 1,073:
</syntaxhighlight>The native ATLAS stack, including Node-RED, Grafana, InfluxDB, and Mosquitto, is not removed by these steps.
</syntaxhighlight>The native ATLAS stack, including Node-RED, Grafana, InfluxDB, and Mosquitto, is not removed by these steps.


=== 18. Summary ===
=== 17. Summary ===
{| class="wikitable"
{| class="wikitable mix-table"
!Step
!Step
!Command / Action
!Command / Action
Line 679: Line 1,088:
|-
|-
|Access
|Access
|[http://&#x3C;ip-do-atlas&#x3E;:8123 http://<atlas-ip>:8123]
|[http://&#x3C;ip-do-atlas&#x3E;:8123 '''<u>http://<atlas-ip>:8123</u>''']
|-
|-
|Configure MQTT
|Configure MQTT
Line 699: Line 1,108:
|sudo docker compose down
|sudo docker compose down
|}
|}
=== 19. Final checklist ===
* Docker installed and functional
* homeassistant container in Up state
* Port 8123 accessible
* MQTT configured in Home Assistant
* configuration.yaml file created with <code>mqtt: !include mqtt.yaml</code>
* mqtt.yaml file created
* AI1..AI4 entities created
* DI1..DI4 entities created
* DO1..DO4 entities created
* Node-RED still accessible on 1880
* Mosquitto still accessible on 1883
* Grafana still accessible on 3000
* InfluxDB still accessible on 8086
* Backup of the ha-config folder considered
atlas-ha-install-v1.tar.gz