Tutorial: ZWave-JS migration on Synology using Docker - applicable to other hosts

I’ve been researching the options, reading articles and asking questions in these forums. Purpose of this thread is to document the different steps and decisions I’ve gone through.

First, my setup. I run home assistant on a Synology NAS running DSM 6.x using Docker. I like using docker as it gives me flexibility in running multiple containers, different instance of HA. I find this useful when developing packages and automations to do it on a test instance rather than monkeying around on the prod system.

Overtime I’ve made most of my config modular in packages and have different package templates for different devices - such that if I deploy a new temp / humidity sensor - I can automate getting the sensor up with high / low alarm limits, alerts, etc. I use shell scripts and sed to automate the generation. It’s nice, since if I change a rule or automation it’s then easy to redeploy. But I digress….

I know that migrations are rarely easy. For example, humans migrated to North America across the bering land bridge. As a lifelong dev, I’ve been through many migrations….

So, one of my main goals is to do the migration in steps, on my own time, identify / mitigate the inevitable issues and then have a seamless prod cutover when I’m ready. Rather than doing an epic 18 hour upgrade and end up tossing the NAS down the stairs :love_you_gesture:.

Since I’m on docker, running the zwavejs2mqtt docker container is the way to go.

Based on some excellent advice from @finity I found out that if you Stop the Zwave (deprecated) Network in HA that releases the stick to be accessible by zwavejs2mqtt. Likewise If you shutdown the zwavejs2mqtt container that releases the stick and you can restart the zwave network in HA. So with this approach I can take zwave outages on the prod system to work on the zwave-js and then switch back when I’m done with the current task or need a break.

Speaking of breaks I need one right now. Next post will be on how to get zwavejs2mqtt setup on Synology docker.

2 Likes

So this is going to be a tutorial?

as I was reading this I thought you were going to ask how to do it until I got to the end and you referenced the conversation we had. :laughing:

(at least I think it was you…there are so many I forget who is who sometimes…)

Terminology Used

  • HA - Home Assistant
  • HA Prod - this is your current Home Assistant System that is currently running. The objective is to have a seamless, uneventful migration of this system to zwave_js
  • old zwave, zwave deprecated - the now deprecated HA driver that we are migrating from
  • jwave_js - the new zwave_js driver we are migrating to.
  • zwave_js container - the docker container running zwavejs2mqtt. In a non-docker environment this would be called the zwave_js add-on. However, I don’t use that and am not sure of the details.

The main cause of failed migrations is not waiting for the zwave-js interview process to complete for battery powered devices. These devices have a configured wake-up interval, often times it’s configured to be 1 day. So what that means is you’d take your prod z-wave offline for up to 24 hours to wait for the interview process to complete - or more likely you get impatient and start removing and re-adding nodes. Once you do that you’ve changed the sticks configuration and there is no seamless way to go back to work working HA prod system. So with the main failure mode known that leads us to the first step,

Step #1 - Go into the zwave (deprecated) integration config panel and for each battery powered device set the wake-up interval to 3600 seconds (e.g 1 hour) and save it. The next time the device wakes up this should become its new interval. Note: this will take up to 24 hours - since a device that already has a 24 hour wake-up isn’t going to wake up earlier. So do this, and come back in a day.

Verify Step #1 - In zwave (deprecated) every node has an entity zwave., these entities have attributes and one of them is the wake-up interval for battery powered devices, So build a Lovelace dashboard with this zwave.* entities or view them in developer tools. Make sure they are all set to 3600. If not retry the first step again and wait another day.

1 Like

Step #2 - zwavejs2mqtt docker container

I use the Synology docker UI to configure my containers and start and stop them. I wanted to continue to do that as it’s a good UI and faster than getting into a shell and using docker commands. Turns out getting this setup was super easy, once some of the confusion is removed.

The zwavejs2mqtt documentation ZwaveJS2Mqtt states:

  • Do not use /dev/ttyUSBX serial devices, as those mappings can change over time.
  • Instead, use the /dev/serial/by-id/X serial device for your Z-Wave stick.

This is likely good advice, but on Synology there is no /dev/serial path, so this advice is not for us. I’ve been using /dev/ttyACM0 with zwave (deprecated) with no issues. You can find your current device in the .storage/core.config_entries file.

Second they talk about passing this device in as part of the docker configuration.

—device=/dev/serial/by-id/insert_stick_reference_here:/dev/zwave

But in Synology the UI does not provide device mapping. I found article that explained how to do it by editing the json config, and then found another article that said as of late 2021 this no longer worked. It did look like folks use docker-compose successfully. But that looked like a learning curve. So I decided to just start the container and see what happens - and sometimes you get lucky!

Step 2.1 - create a folder in Synology for the container. I created a folder under the existing docker folder /docker/zwavejs2mqtt

Step 2.2 - use the docker UI to grab the latest image and select launch.

Give it a name and select the “Execute Container using High Privilege”. Yes, this is a bad security practice, doing this however gives the container access to all the devices. Later on, I’ll find a way to fix. Select the advanced button

Map the folder we created into the container.

I run most images on the host network, I also use the Synology firewall and by default there is no access to ports in this container.

Lastly go into environment and add your TZ if you want the logs in local time.

From there launch the container. Go into the Synology firewall and add port 8091 to allow access from your subnet or ip_address. Go to that URL and the jwavejs control panel should appear. Go around and explore the UI and read the docs. Two things you should check out:

  1. Enable logging at info or debug level, these files should end up in the Synology folder.
  2. Under zwave, there is a combo box to select the device, open and you should see /dev/ttyACM0 - Do not select it yet - we will do that later
  3. Find the home assistant config and make sure the websocket interface is enabled and MQTT is not.

That it, shutdown the container and we’ll wait for Step #1 to complete.

Step 3 - Objective get zwavejs2mqtt initialized and get the list of entity ids to plan the mapping. Allocate 90 minutes of HA zwave downtime.

  • Stop the zwave network in the prod HA
  • Start up the zwavejs container, go into the control panel, and set it to use /dev/ttyACM0, press save. It should then start finding devices. Initially they will all be “unknown” devices, but don’t panic. As it goes through the interview process the display will update. The battery powered take the longest - up to an hour, so there’s lots of time to wait.
  • As devices get interviewed give them a name and an area. Give them the same name you are already using in HA. For example if you have sensor.living_room_multisensor_temperature then name the node living_room_multisensor,
  • Get a new HA docker container setup with empty configuration. We will use this to connect to zwavejs to get the entity list. On my system I put this on port 9123, because my prod HA runs on 8123. To change the port refer to this documentation. HTTP - Home Assistant
  • Start this container up (you may need to open 9123 on the firewall), login and make sure it’s working.
  • Wait for the last battery devices to get interviewed. Once complete review the names you gave.
  • Add the zwavejs integration to the new HA container, check the device list, once happy shut the container down.
  • That’s it for the online session. Shutdown the zwavejs_mqtt, wait a minute, and restart the zwave network on HA prod.

Step 4 - Entity Mapping, The objective of this step is to get the list on entities from the new system and prod system, map them in excel, identify mapping issues and then update the entity names in the new system. Alternatives could be to use the migration tool. I did not use it.

A) In the prod system run this in developer tools


{%- for node, zstates in states | selectattr('attributes.node_id', 'in', range(1000)) | groupby('attributes.node_id') %}

{%- for s in zstates %}
Node {{ node }};{{ s.name }};{{ s.entity_id }}{% endfor %}

{%- endfor %}

This will output a semicolon separated list, copy this, paste into Excel, use the excel text mapping tool to parse the ; into columns. I’ve attached my excel spreadsheet if you want to start with that. This data should go into Sheet 2

B. In the new HA system, run this to get the list of entities.

{%- for s in zstates %}
{{ s.entity_id }}
{% endfor %}

Copy this list and paste into Excel - sheet 1 column A.

C. Reconcile. While this is manual it did not take long to accomplish and it identified gaps in the mappings. Most of the gaps were around motion and water sensors - before you’d get a sensor and have to test for 23, now you get a binary_sensor. Anyways my process was to open a second excel window. Filter sheet two on Node ID, the filter sheet 1 on the Name (e.g. water_sensor_1) and then paste the existing entity ids into column 2. I then used a calculation on sheet 1 column 3 to grab the Name from sheet 2.

D. Do the mapping. For this I installed GitHub - home-assistant/cli: Home Assistant command line interface
This is a command line tool that can do stuff like change entity ids. I then saved sheet 1 off as a CSV and ran these scripts

This does the entity Id remapping on your NEW test system


export HASS_SERVER="http://192.168.50.70:9123"
export HASS_TOKEN="See docs”
sed 's/\r$//' zwave_mapping.csv | while IFS=, read old new name need_change used
    do
		if [ "$old" = "zwave_entity_id" ] 
		then
		   echo "Skipping: header line"
		elif [ "$name" = "#N/A" ] 
		then
		   echo "Skipping: No name provided $new $name"
		else 
		   echo "Updating: $new $name"
		   hass-cli entity rename --name "$name" "$new" | tee ./hass-cli-temp.txt
		   if grep -Fq "success: true" ./hass-cli-temp.txt
		   then
		      printf "Success: $new $name\n"
		   else
		      printf "ERROR: failed to update name $new $name\n"
		   fi
		fi
	done

Then run this to set the Names

export HASS_SERVER="http://192.168.50.70:9123"
export HASS_TOKEN=“see cli docs lkIVRUWyEgleGJGsLddeqC0MdFyq45zF-TH2EWQw"
sed 's/\r$//' zwave_mapping.csv | while IFS=, read old new name need_change used
    do
		if [ "$old" = "zwave_entity_id" ] 
		then
		   echo "Skipping: header line"
		elif [ "$name" = "#N/A" ] 
		then
		   echo "Skipping: No name provided $new $name"
		else 
		   echo "Updating: $new $name"
		   hass-cli entity rename --name "$name" "$new" | tee ./hass-cli-temp.txt
		   if grep -Fq "success: true" ./hass-cli-temp.txt
		   then
		      printf "Success: $new $name\n"
		   else
		      printf "ERROR: failed to update name $new $name\n"
		   fi
		fi
	done

At this point you have now have a mapping file, and tools to automate the mapping. As you find errors in later steps you will continue to update this mapping file. I reset my test system several times in order to get a clean run. Just do this. 1) stop zwave network on prod 2) start up zwavejs 3) go into HA test and delete the zwave_js integration and add it back, this will revert all the entities.

1 Like

I install the Docker Image on my Synology DSM 7.1-42661 Update 2.
after installing the docker container runs, and I can access it through the Web interface (no Zwave stick inserted yet, still testing …)
all is well untill I restart the docker container …
then it immediately crashes itself every time …
huh ?
what am I doing wrong ?

this is the log :

/bin/sh: git: not found
2022-06-11 13:45:49.929 INFO APP: Version: 6.5.2
2022-06-11 13:45:49.933 INFO APP: Application path:/usr/src/app
 ______                       _     ___                  _   _   
|___  /                      (_)   |__ \                | | | |  
   / /_      ____ ___   _____ _ ___   ) |_ __ ___   __ _| |_| |_ 
  / /\ \ /\ / / _` \ \ / / _ \ / __| / /| '_ ` _ \ / _` | __| __|
 / /__\ V  V / (_| |\ V /  __/ \__ \/ /_| | | | | | (_| | |_| |_ 
/_____|\_/\_/ \__,_| \_/ \___| |___/____|_| |_| |_|\__, |\__|\__|
                            _/ |                      | |        
                           |__/                       |_|        
2022-06-11 13:45:49.958 WARN STORE: settings.json not found2022-06-11 13:45:49.974 WARN STORE: scenes.json not found
2022-06-11 13:45:49.976 WARN STORE: nodes.json not found
2022-06-11 13:45:49.995 WARN STORE: users.json not found
2022-06-11 13:45:50.025 INFO APP: Listening on port 8091 host 0.0.0.0 protocol HTTP
2022-06-11 13:45:50.220 ERROR GATEWAY: Zwave settings are not valid
2022-06-11 13:46:05.947 INFO APP: GET / 200 24.661 ms - 1369
2022-06-11 13:46:05.997 INFO APP: GET /static/css/app.0726e08516ca09f75bf9.css 200 11.309 ms - 643916
2022-06-11 13:46:06.014 INFO APP: GET /static/js/app.f738fc16954934fc400b.js 200 9.912 ms - 2076062
2022-06-11 13:46:06.265 INFO APP: GET /api/auth-enabled 200 10.069 ms - 29
2022-06-11 13:46:06.418 INFO APP: GET /static/logo.png 200 2.527 ms - 10014
2022-06-11 13:46:06.601 INFO APP: GET /api/settings 200 180.548 ms - 12381
2022-06-11 13:46:06.605 INFO APP: GET /static/favicons/favicon-32x32.png 200 144.002 ms - 1831
2022-06-11 13:46:06.609 INFO APP: GET /static/fonts/MaterialIcons-Regular.fa3334f.woff2 200 143.919 ms - 82492
2022-06-11 13:46:06.617 INFO APP: GET /static/favicons/favicon-32x32.png 304 2.319 ms - -
2022-06-11 13:46:06.623 INFO APP: GET /api/auth-enabled 304 3.360 ms - -
2022-06-11 13:46:16.747 INFO APP: POST /api/statistics 200 26.599 ms - 90
2022-06-11 13:46:51.011 WARN APP: Shutdown detected: closing clients...
2022-06-11 13:46:51.012 INFO GATEWAY: Closing Gateway...
/bin/sh: git: not found


2022-06-11 13:46:54.500 INFO APP: Version: 6.5.2
2022-06-11 13:46:54.504 INFO APP: Application path:/usr/src/app
 ______                       _     ___                  _   _   
|___  /                      (_)   |__ \                | | | |  
   / /_      ____ ___   _____ _ ___   ) |_ __ ___   __ _| |_| |_ 
  / /\ \ /\ / / _` \ \ / / _ \ / __| / /| '_ ` _ \ / _` | __| __|
 / /__\ V  V / (_| |\ V /  __/ \__ \/ /_| | | | | | (_| | |_| |_ 
/_____|\_/\_/ \__,_| \_/ \___| |___/____|_| |_| |_|\__, |\__|\__|
                            _/ |                      | |        
                           |__/                       |_|        
2022-06-11 13:46:54.551 WARN STORE: scenes.json not found
2022-06-11 13:46:54.552 WARN STORE: nodes.json not found
2022-06-11 13:46:54.577 INFO APP: Listening on port 8091 host 0.0.0.0 protocol HTTP
TypeError: Cannot read property 'disabled' of undefined
    at Gateway.start (/usr/src/app/server/lib/Gateway.js:180:29)
    at startGateway (/usr/src/app/server/app.js:236:14)
    at startServer (/usr/src/app/server/app.js:176:11)
/bin/sh: git: not found


2022-06-11 13:47:47.522 INFO APP: Version: 6.5.2
2022-06-11 13:47:47.525 INFO APP: Application path:/usr/src/app
 ______                       _     ___                  _   _   
|___  /                      (_)   |__ \                | | | |  
   / /_      ____ ___   _____ _ ___   ) |_ __ ___   __ _| |_| |_ 
  / /\ \ /\ / / _` \ \ / / _ \ / __| / /| '_ ` _ \ / _` | __| __|
 / /__\ V  V / (_| |\ V /  __/ \__ \/ /_| | | | | | (_| | |_| |_ 
/_____|\_/\_/ \__,_| \_/ \___| |___/____|_| |_| |_|\__, |\__|\__|
                            _/ |                      | |        
                           |__/                       |_|        
2022-06-11 13:47:47.574 WARN STORE: scenes.json not found
SyntaxError: /usr/src/app/store/nodes.json: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at _readFile (/usr/src/app/node_modules/jsonfile/index.js:25:16)
    at StorageHelper._getFile (/usr/src/app/server/lib/jsonStore.js:51:20)
    at StorageHelper.init (/usr/src/app/server/lib/jsonStore.js:42:25)

/bin/sh: git: not found
2022-06-11 13:54:20.047 INFO APP: Version: 6.5.2
2022-06-11 13:54:20.052 INFO APP: Application path:/usr/src/app
 ______                       _     ___                  _   _   
|___  /                      (_)   |__ \                | | | |  
   / /_      ____ ___   _____ _ ___   ) |_ __ ___   __ _| |_| |_ 
  / /\ \ /\ / / _` \ \ / / _ \ / __| / /| '_ ` _ \ / _` | __| __|
 / /__\ V  V / (_| |\ V /  __/ \__ \/ /_| | | | | | (_| | |_| |_ 
/_____|\_/\_/ \__,_| \_/ \___| |___/____|_| |_| |_|\__, |\__|\__|
                            _/ |                      | |        
                           |__/                       |_|        
2022-06-11 13:54:20.130 WARN STORE: scenes.json not found
SyntaxError: /usr/src/app/store/nodes.json: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at _readFile (/usr/src/app/node_modules/jsonfile/index.js:25:16)
    at StorageHelper._getFile (/usr/src/app/server/lib/jsonStore.js:51:20)
    at StorageHelper.init (/usr/src/app/server/lib/jsonStore.js:42:25)

It looks like the storage files are corrupted. Did you map a folder in to the container for storage?

If not, you should do that. If so, try deleting the nodes file and restarting.

Also 6.5.2 is a very old version. You may want to use the latest.

yes I did, but I’m not sure if it’s correct

I just gave it the name “data” out of the blue, because I didn’t know what else to call it …

would that be ok ?

No that’s wrong. There is a screen shot of the correct configuration further up in this thread.

I changed it to “/usr/src/app/store” (as mentioned in the screenshot above) and it works … for 1 time …

when restarting again, it crashes again … grrrrr

/bin/sh: git: not found
2022-06-11 14:22:51.108 INFO APP: Version: 6.5.2
2022-06-11 14:22:51.112 INFO APP: Application path:/usr/src/app
 ______                       _     ___                  _   _   
|___  /                      (_)   |__ \                | | | |  
   / /_      ____ ___   _____ _ ___   ) |_ __ ___   __ _| |_| |_ 
  / /\ \ /\ / / _` \ \ / / _ \ / __| / /| '_ ` _ \ / _` | __| __|
 / /__\ V  V / (_| |\ V /  __/ \__ \/ /_| | | | | | (_| | |_| |_ 
/_____|\_/\_/ \__,_| \_/ \___| |___/____|_| |_| |_|\__, |\__|\__|
                            _/ |                      | |        
                           |__/                       |_|        
2022-06-11 14:22:51.160 WARN STORE: scenes.json not found
SyntaxError: /usr/src/app/store/nodes.json: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at _readFile (/usr/src/app/node_modules/jsonfile/index.js:25:16)
    at StorageHelper._getFile (/usr/src/app/server/lib/jsonStore.js:51:20)
    at StorageHelper.init (/usr/src/app/server/lib/jsonStore.js:42:25)

with a newer version, it seems to work better …

2022-06-11 14:54:39.907 INFO APP: Version: 6.12.0
2022-06-11 14:54:39.911 INFO APP: Application path:/usr/src/app
 ______                       _     ___                  _   _   
|___  /                      (_)   |__ \                | | | |  
   / /_      ____ ___   _____ _ ___   ) |_ __ ___   __ _| |_| |_ 
  / /\ \ /\ / / _` \ \ / / _ \ / __| / /| '_ ` _ \ / _` | __| __|
 / /__\ V  V / (_| |\ V /  __/ \__ \/ /_| | | | | | (_| | |_| |_ 
/_____|\_/\_/ \__,_| \_/ \___| |___/____|_| |_| |_|\__, |\__|\__|
                            _/ |                      | |        
                           |__/                       |_|        
2022-06-11 14:54:39.952 WARN STORE: scenes.json not found
2022-06-11 14:54:39.993 INFO APP: Listening on port 8091 host 0.0.0.0 protocol HTTP
2022-06-11 14:54:40.067 WARN ZWAVE: Zwave driver not inited, no port configured
1 Like

I have it up and running now … so time to move the USB stick (Aeon Gen5) to the Synology …

I plugged it in and the it’s light turns blue, so it looks okay …

I used the serial port “/dev/ttyACM0” as advised, although this “ACM0” wasn’t in the dropdown (which I find suspicious)

image

and of course, it doesn’t seem to find it there …

what am I doing wrong ?

From a shell command prompt do this

ls /dev

Do you see ttyACM0?

No I don’t … :frowning:

pascal_admin@DISKSTATION:~$ ls /dev
block             network_throughput  ptyc3  ptyed  ptyr7  ptyu1  ptywb  ptyz5   sdd1       tty30  ttya2  ttycc  ttyp6  ttys0  ttyu6  ttyx0  ttyza
bsg               null                ptyc4  ptyee  ptyr8  ptyu2  ptywc  ptyz6   sdd2       tty31  ttya3  ttycd  ttyp7  ttyS0  ttyu7  ttyx1  ttyzb
btrfs-control     port                ptyc5  ptyef  ptyr9  ptyu3  ptywd  ptyz7   sdd5       tty32  ttya4  ttyce  ttyp8  ttys1  ttyu8  ttyx2  ttyzc
bus               ptmx                ptyc6  ptyp0  ptyra  ptyu4  ptywe  ptyz8   sg0        tty33  ttya5  ttycf  ttyp9  ttyS1  ttyu9  ttyx3  ttyzd
char              ptp0                ptyc7  ptyp1  ptyrb  ptyu5  ptywf  ptyz9   sg1        tty34  ttya6  ttyd0  ttypa  ttys2  ttyua  ttyx4  ttyze
console           ptp1                ptyc8  ptyp2  ptyrc  ptyu6  ptyx0  ptyza   sg2        tty35  ttya7  ttyd1  ttypb  ttyS2  ttyub  ttyx5  ttyzf
core              pts                 ptyc9  ptyp3  ptyrd  ptyu7  ptyx1  ptyzb   sg3        tty36  ttya8  ttyd2  ttypc  ttys3  ttyuc  ttyx6  urandom
cpu               ptya0               ptyca  ptyp4  ptyre  ptyu8  ptyx2  ptyzc   sg4        tty37  ttya9  ttyd3  ttypd  ttyS3  ttyud  ttyx7  vcs
cpu_dma_latency   ptya1               ptycb  ptyp5  ptyrf  ptyu9  ptyx3  ptyzd   shm        tty38  ttyaa  ttyd4  ttype  ttys4  ttyue  ttyx8  vcs1
dm-0              ptya2               ptycc  ptyp6  ptys0  ptyua  ptyx4  ptyze   snapshot   tty39  ttyab  ttyd5  ttypf  ttys5  ttyuf  ttyx9  vcs2
dm-1              ptya3               ptycd  ptyp7  ptys1  ptyub  ptyx5  ptyzf   stderr     tty4   ttyac  ttyd6  ttyq0  ttys6  ttyv0  ttyxa  vcs3
dm-2              ptya4               ptyce  ptyp8  ptys2  ptyuc  ptyx6  ram0    stdin      tty40  ttyad  ttyd7  ttyq1  ttys7  ttyv1  ttyxb  vcs4
dri               ptya5               ptycf  ptyp9  ptys3  ptyud  ptyx7  ram1    stdout     tty41  ttyae  ttyd8  ttyq2  ttys8  ttyv2  ttyxc  vcs5
fb0               ptya6               ptyd0  ptypa  ptys4  ptyue  ptyx8  ram10   synobios   tty42  ttyaf  ttyd9  ttyq3  ttys9  ttyv3  ttyxd  vcs6
fd                ptya7               ptyd1  ptypb  ptys5  ptyuf  ptyx9  ram11   synoboot   tty43  ttyb0  ttyda  ttyq4  ttysa  ttyv4  ttyxe  vcsa
full              ptya8               ptyd2  ptypc  ptys6  ptyv0  ptyxa  ram12   synoboot1  tty44  ttyb1  ttydb  ttyq5  ttysb  ttyv5  ttyxf  vcsa1
fuse              ptya9               ptyd3  ptypd  ptys7  ptyv1  ptyxb  ram13   synoboot2  tty45  ttyb2  ttydc  ttyq6  ttysc  ttyv6  ttyy0  vcsa2
i2c-0             ptyaa               ptyd4  ptype  ptys8  ptyv2  ptyxc  ram14   tty        tty46  ttyb3  ttydd  ttyq7  ttysd  ttyv7  ttyy1  vcsa3
i2c-1             ptyab               ptyd5  ptypf  ptys9  ptyv3  ptyxd  ram15   tty0       tty47  ttyb4  ttyde  ttyq8  ttyse  ttyv8  ttyy2  vcsa4
i2c-2             ptyac               ptyd6  ptyq0  ptysa  ptyv4  ptyxe  ram2    tty1       tty48  ttyb5  ttydf  ttyq9  ttysf  ttyv9  ttyy3  vcsa5
i2c-3             ptyad               ptyd7  ptyq1  ptysb  ptyv5  ptyxf  ram3    tty10      tty49  ttyb6  ttye0  ttyqa  ttyt0  ttyva  ttyy4  vcsa6
i2c-4             ptyae               ptyd8  ptyq2  ptysc  ptyv6  ptyy0  ram4    tty11      tty5   ttyb7  ttye1  ttyqb  ttyt1  ttyvb  ttyy5  vg1
kmem              ptyaf               ptyd9  ptyq3  ptysd  ptyv7  ptyy1  ram5    tty12      tty50  ttyb8  ttye2  ttyqc  ttyt2  ttyvc  ttyy6  vga_arbiter
kmsg              ptyb0               ptyda  ptyq4  ptyse  ptyv8  ptyy2  ram6    tty13      tty51  ttyb9  ttye3  ttyqd  ttyt3  ttyvd  ttyy7  vhost-scsi
log               ptyb1               ptydb  ptyq5  ptysf  ptyv9  ptyy3  ram7    tty14      tty52  ttyba  ttye4  ttyqe  ttyt4  ttyve  ttyy8  zero
loop0             ptyb2               ptydc  ptyq6  ptyt0  ptyva  ptyy4  ram8    tty15      tty53  ttybb  ttye5  ttyqf  ttyt5  ttyvf  ttyy9  zram0
loop1             ptyb3               ptydd  ptyq7  ptyt1  ptyvb  ptyy5  ram9    tty16      tty54  ttybc  ttye6  ttyr0  ttyt6  ttyw0  ttyya  zram1
loop2             ptyb4               ptyde  ptyq8  ptyt2  ptyvc  ptyy6  random  tty17      tty55  ttybd  ttye7  ttyr1  ttyt7  ttyw1  ttyyb  zram2
loop3             ptyb5               ptydf  ptyq9  ptyt3  ptyvd  ptyy7  rtc0    tty18      tty56  ttybe  ttye8  ttyr2  ttyt8  ttyw2  ttyyc  zram3
loop4             ptyb6               ptye0  ptyqa  ptyt4  ptyve  ptyy8  sda     tty19      tty57  ttybf  ttye9  ttyr3  ttyt9  ttyw3  ttyyd
loop5             ptyb7               ptye1  ptyqb  ptyt5  ptyvf  ptyy9  sda1    tty2       tty58  ttyc0  ttyea  ttyr4  ttyta  ttyw4  ttyye
loop6             ptyb8               ptye2  ptyqc  ptyt6  ptyw0  ptyya  sda2    tty20      tty59  ttyc1  ttyeb  ttyr5  ttytb  ttyw5  ttyyf
loop7             ptyb9               ptye3  ptyqd  ptyt7  ptyw1  ptyyb  sda5    tty21      tty6   ttyc2  ttyec  ttyr6  ttytc  ttyw6  ttyz0
loop-control      ptyba               ptye4  ptyqe  ptyt8  ptyw2  ptyyc  sdb     tty22      tty60  ttyc3  ttyed  ttyr7  ttytd  ttyw7  ttyz1
mapper            ptybb               ptye5  ptyqf  ptyt9  ptyw3  ptyyd  sdb1    tty23      tty61  ttyc4  ttyee  ttyr8  ttyte  ttyw8  ttyz2
mcelog            ptybc               ptye6  ptyr0  ptyta  ptyw4  ptyye  sdb2    tty24      tty62  ttyc5  ttyef  ttyr9  ttytf  ttyw9  ttyz3
md0               ptybd               ptye7  ptyr1  ptytb  ptyw5  ptyyf  sdb5    tty25      tty63  ttyc6  ttyp0  ttyra  ttyu0  ttywa  ttyz4
md1               ptybe               ptye8  ptyr2  ptytc  ptyw6  ptyz0  sdc     tty26      tty7   ttyc7  ttyp1  ttyrb  ttyu1  ttywb  ttyz5
md2               ptybf               ptye9  ptyr3  ptytd  ptyw7  ptyz1  sdc1    tty27      tty8   ttyc8  ttyp2  ttyrc  ttyu2  ttywc  ttyz6
mem               ptyc0               ptyea  ptyr4  ptyte  ptyw8  ptyz2  sdc2    tty28      tty9   ttyc9  ttyp3  ttyrd  ttyu3  ttywd  ttyz7
memory_bandwidth  ptyc1               ptyeb  ptyr5  ptytf  ptyw9  ptyz3  sdc5    tty29      ttya0  ttyca  ttyp4  ttyre  ttyu4  ttywe  ttyz8
network_latency   ptyc2               ptyec  ptyr6  ptyu0  ptywa  ptyz4  sdd     tty3       ttya1  ttycb  ttyp5  ttyrf  ttyu5  ttywf  ttyz9

and …

pascal_admin@DISKSTATION:~$ dmesg | grep tty
[    0.000000] Kernel command line: root=/dev/md0 earlyprintk=apl console=ttyS2,115200n8 ihd_num=4 netif_num=2 HddHotplug=1 SataPortMap=23 sata_remap=0>2:1>3:2>0:3>1 syno_hw_version=DS918+ vender_format_version=2 syno_hdd_detect=18,179,176,175 syno_hdd_enable=21,20,19,9 syno_usb_vbus_gpio=13@0000:00:15.0@1,11@0000:00:15.0@2 sn=18B0PDN106901 macs=0011329e6ac1,0011329e6ac2
[    5.112794] dw-apb-uart.1: ttyS0 at MMIO 0x9141c000 (irq = 44, base_baud = 115200) is a 16550A
[    5.122305] console [ttyS2] enabled
[    5.165777] dw-apb-uart.2: ttyS1 at MMIO 0x9141e000 (irq = 45, base_baud = 115200) is a 16550A
[    5.167681] console [ttyS2] disabled
[    5.167901] dw-apb-uart.3: ttyS2 at MMIO 0x91420000 (irq = 6, base_baud = 115200) is a 16550A
[    5.167924] console [ttyS2] enabled
[    5.173615] dw-apb-uart.4: ttyS3 at MMIO 0x91422000 (irq = 47, base_baud = 115200) is a 16550A
[   73.482696] synobios open /dev/ttyS1 success
[  144.654775] synobios open /dev/ttyS1 success
[  162.824626] systemd[1]: Created slice system-serial\x2dgetty.slice.
[  162.835399] systemd[1]: Starting system-serial\x2dgetty.slice.
[  163.762582] synobios open /dev/ttyS1 success
[546084.718188] ttyS3 - failed to request DMA

maybe as extra info :

I have a DS918+

DSM version : 7.1-42661 Update 2

because I read somewhere that DSM 7 would have problems using an Aeon Gen 5 USB stick ?

Yes, dsm 7 requires some additional work. I’m still on 6.x

This guide looks helpful

I’m installing it on a Raspi in snap package now … I’m too worried that the Synology docker container would get in trouble each time there is a DSM update …