Asynchronous Python API for Synology DSM
Installation
[sudo] pip install py-synologydsm-api
Usage
You can import the module as synology_dsm
.
Constructor
SynologyDSM(
session,
dsm_ip,
dsm_port,
username,
password,
use_https=False,
timeout=10,
device_token=None,
debugmode=False,
)
For session
a valid aiohttp.ClientSession
needs to be provided. If ssl verification should be truned off, configure the session accordingly (eq. aiohttp.ClientSession(connector=aiohttp.TCPConnector(verify_ssl=False)
)
device_token
should be added when using a two-step authentication account, otherwise DSM will ask to login with a One Time Password (OTP) and requests will fail (see the login section for more details).
Default timeout
is 10 seconds. SynologyDSM
also takes a aiohttp.ClientTimeout
as timeout
.
Login
Use the login()
function to authenticate first, otherwise a SynologyDSMNotLoggedInException
is raised.
It will return a boolean if it successed or faild to authenticate to DSM.
If your account need a two-step authentication (2SA), login()
will raise SynologyDSMLogin2SARequiredException
.
Call the function again with a One Time Password (OTP) as parameter, like login("123456")
(better to be a string to handle first zero).
Store the device_token
property so that you do not need to reconnect with password the next time you open a new SynologyDSM
session.
Code example
Every API has an update()
function that is needed to get the first data, then the data is cached and updated at the next update()
call.
The SynologyDSM
class can also update()
all APIs at once.
import asyncio
import aiohttp
from synology_dsm import SynologyDSM
async def main():
print("Creating Valid API")
async with aiohttp.ClientSession(
connector=aiohttp.TCPConnector(verify_ssl=False)
) as session:
await do(session)
async def do(session: aiohttp.ClientSession):
api = SynologyDSM(session, "<IP/DNS>", "<port>", "<username>", "<password>")
await api.login()
print("=== Information ===")
await api.information.update()
print("Model: " + str(api.information.model))
print("RAM: " + str(api.information.ram) + " MB")
print("Serial number: " + str(api.information.serial))
print("Temperature: " + str(api.information.temperature) + " °C")
print("Temp. warning: " + str(api.information.temperature_warn))
print("Uptime: " + str(api.information.uptime))
print("Full DSM version:" + str(api.information.version_string))
print("--")
print("=== Utilisation ===")
await api.utilisation.update()
print("CPU Load: " + str(api.utilisation.cpu_total_load) + " %")
print("Memory Use: " + str(api.utilisation.memory_real_usage) + " %")
print("Net Up: " + str(api.utilisation.network_up()))
print("Net Down: " + str(api.utilisation.network_down()))
print("--")
print("=== Storage ===")
await api.storage.update()
for volume_id in api.storage.volumes_ids:
print("ID: " + str(volume_id))
print("Status: " + str(api.storage.volume_status(volume_id)))
print("% Used: " + str(api.storage.volume_percentage_used(volume_id)) + " %")
print("--")
for disk_id in api.storage.disks_ids:
print("ID: " + str(disk_id))
print("Name: " + str(api.storage.disk_name(disk_id)))
print("S-Status: " + str(api.storage.disk_smart_status(disk_id)))
print("Status: " + str(api.storage.disk_status(disk_id)))
print("Temp: " + str(api.storage.disk_temp(disk_id)))
print("--")
print("=== Shared Folders ===")
await api.share.update()
for share_uuid in api.share.shares_uuids:
print("Share name: " + str(api.share.share_name(share_uuid)))
print("Share path: " + str(api.share.share_path(share_uuid)))
print("Space used: " + str(api.share.share_size(share_uuid, human_readable=True)))
print("Recycle Bin Enabled: " + str(api.share.share_recycle_bin(share_uuid)))
print("--")
if __name__ == "__main__":
asyncio.run(main())
Download Station usage
import asyncio
import aiohttp
from synology_dsm import SynologyDSM
async def main():
print("Creating Valid API")
async with aiohttp.ClientSession(
connector=aiohttp.TCPConnector(verify_ssl=False)
) as session:
await do(session)
async def do(session: aiohttp.ClientSession):
api = SynologyDSM(session, "<IP/DNS>", "<port>", "<username>", "<password>")
await api.login()
if "SYNO.DownloadStation.Info" in api.apis:
await api.download_station.get_info()
await api.download_station.get_config()
await api.download_station.create("http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
await api.download_station.pause("dbid_1")
await api.download_station.resume(["dbid_1", "dbid_2"])
await api.download_station.delete("dbid_3")
await api.download_station.update()
if __name__ == "__main__":
asyncio.run(main())
External USB storage usage
import asyncio
import aiohttp
from synology_dsm import SynologyDSM
async def main():
print("Creating Valid API")
async with aiohttp.ClientSession(
connector=aiohttp.TCPConnector(verify_ssl=False)
) as session:
await do(session)
async def do(session: aiohttp.ClientSession):
api = SynologyDSM(session, "<IP/DNS>", "<port>", "<username>", "<password>")
await api.login()
await api.external_usb.update()
for device in api.external_usb.get_devices.values():
print("Name: " + str(device.device_name))
print("Size: " + str(device.device_size_total(human_readable=True))
print("Size in mb: " + str(device.device_size_total())
print("Partitions size total: " + str(device.partitions_all_size_total(human_readable=True)))
print("Partitions size used: " + str(device.partitions_all_size_used(human_readable=True)))
print("Partitions % Used: " + str(device.partitions_all_percentage_used ) + " %")
print(" === Partitions ===")
for part in device.device_partitions.values():
print(" Share name: " + str(part.share_name))
print(" Filesystem: " + str(part.filesystem))
print(" Size: " + str(part.partition_size_total(human_readable=True)))
print(" Used: " + str(part.partition_size_used(human_readable=True)))
print(" % Used: " + str(part.partition_percentage_used) + " %")
if __name__ == "__main__":
asyncio.run(main())
Photos usage
import asyncio
import aiohttp
from synology_dsm import SynologyDSM
async def main():
print("Creating Valid API")
async with aiohttp.ClientSession(
connector=aiohttp.TCPConnector(verify_ssl=False)
) as session:
await do(session)
async def do(session: aiohttp.ClientSession):
api = SynologyDSM(session, "<IP/DNS>", "<port>", "<username>", "<password>")
await api.login()
albums = await api.photos.get_albums()
for album in albums:
print(f"'{album.name}' has {album.item_count} items")
items = await api.photos.get_items_from_album(album)
for item in items:
print(f"{item.file_name}")
with open(item.file_name, "wb") as fh:
fh.write(await api.photos.download_item(item))
items = await api.photos.get_items_from_search("pinky and the brain")
for item in items:
with open(item.file_name, "wb") as fh:
fh.write(await api.photos.download_item(item))
if __name__ == "__main__":
asyncio.run(main())
Surveillance Station usage
import asyncio
import aiohttp
from synology_dsm import SynologyDSM
async def main():
print("Creating Valid API")
async with aiohttp.ClientSession(
connector=aiohttp.TCPConnector(verify_ssl=False)
) as session:
await do(session)
async def do(session: aiohttp.ClientSession):
api = SynologyDSM(session, "<IP/DNS>", "<port>", "<username>", "<password>")
await api.login()
surveillance = api.surveillance_station
await surveillance.update()
cameras = surveillance.get_all_cameras()
camera_id = cameras[0].camera_id
camera = surveillance.get_camera(camera_id)
motion_setting = camera.is_motion_detection_enabled
await surveillance.get_camera_image(camera_id)
await surveillance.update()
home_mode_status = await surveillance.get_home_mode_status()
await surveillance.set_home_mode(True)
if __name__ == "__main__":
asyncio.run(main())
System usage
import asyncio
import aiohttp
from synology_dsm import SynologyDSM
async def main():
print("Creating Valid API")
async with aiohttp.ClientSession(
connector=aiohttp.TCPConnector(verify_ssl=False)
) as session:
await do(session)
async def do(session: aiohttp.ClientSession):
api = SynologyDSM(session, "<IP/DNS>", "<port>", "<username>", "<password>")
await api.login()
system = api.system
await system.reboot()
await system.shutdown()
await system.update()
system.cpu_clock_speed
system.cpu_cores
system.cpu_family
system.cpu_series
system.enabled_ntp
system.ntp_server
system.firmware_ver
system.model
system.ram_size
system.serial
system.sys_temp
system.time
system.time_zone
system.time_zone_desc
system.up_time
system.usb_dev
if __name__ == "__main__":
asyncio.run(main())
Upgrade usage
import asyncio
import aiohttp
from synology_dsm import SynologyDSM
async def main():
print("Creating Valid API")
async with aiohttp.ClientSession(
connector=aiohttp.TCPConnector(verify_ssl=False)
) as session:
await do(session)
async def do(session: aiohttp.ClientSession):
api = SynologyDSM(session, "<IP/DNS>", "<port>", "<username>", "<password>")
await api.login()
upgrade = api.upgrade
await upgrade.update()
if upgrade.update_available:
do something ...
upgrade.available_version
upgrade.reboot_needed
upgrade.service_restarts
if __name__ == "__main__":
asyncio.run(main())
Credits / Special Thanks
Found Synology API "documentation" on this repo : https://github.com/kwent/syno/tree/master/definitions
Official references