Skip to content

Commit

Permalink
MClimate: add devices - 16ADS, Button, Open/close; add profileIds (#867)
Browse files Browse the repository at this point in the history
* New MClimate devices: 16ASPM, CO2 Display Lite

* New MClimate devices: 16ASPM, CO2 Display Lite

* MClimate Vicki updated decoder

* update mclimate index; fix names

* MCliamte: add devices - 16ADS, Button, Open/close; add profileIds

---------

Co-authored-by: Yordan <[email protected]>
Co-authored-by: Jaime Trinidad <[email protected]>
  • Loading branch information
3 people authored Jan 28, 2025
1 parent 0ef478a commit b64c9ef
Show file tree
Hide file tree
Showing 17 changed files with 866 additions and 2 deletions.
11 changes: 11 additions & 0 deletions vendor/mclimate/16ads-codec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
uplinkDecoder:
fileName: 16ads.js
examples:
- description: Periodic uplink
input:
fPort: 2
bytes: [0x01, 0x1C, 0x01]
output:
data:
internalTemperature: 28
relayState: 'ON'
8 changes: 8 additions & 0 deletions vendor/mclimate/16ads-profile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
supportsClassB: false
supportsClassC: true
macVersion: 1.0.3
regionalParametersVersion: RP001-1.0.3-RevA
supportsJoin: true
maxEIRP: 16
supports32bitFCnt: true
classCTimeout: 60
142 changes: 142 additions & 0 deletions vendor/mclimate/16ads.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
const decodeUplink = (input) => {
try {
let { bytes } = input;
let data = {};

const handleKeepalive = (bytes, data) => {
// Temperature sign and internal temperature
const isNegative = (bytes[1] & 0x80) !== 0; // Check the 7th bit for the sign

let temperature = bytes[1] & 0x7F; // Mask out the 7th bit to get the temperature value
data.internalTemperature = isNegative ? -temperature : temperature;

// Relay state
data.relayState = bytes[2] === 0x01 ? "ON" : "OFF";

return data;
};

const handleResponse = (bytes, data) => {
let commands = bytes.map(byte => (`0${byte.toString(16)}`).slice(-2)).slice(0, -3);
let command_len = 0;

commands.forEach((command, i) => {
switch (command) {
case '04': {
command_len = 2;
const hardwareVersion = commands[i + 1];
const softwareVersion = commands[i + 2];
data.deviceVersions = {
hardware: Number(hardwareVersion),
software: Number(softwareVersion),
};
break;
}
case '12': {
command_len = 1;
data.keepAliveTime = parseInt(commands[i + 1], 16);
break;
}
case '19': {
command_len = 1;
const commandResponse = parseInt(commands[i + 1], 16);
const periodInMinutes = (commandResponse * 5) / 60;
data.joinRetryPeriod = periodInMinutes;
break;
}
case '1b': {
command_len = 1;
data.uplinkType = parseInt(commands[i + 1], 16);
break;
}
case '1d': {
command_len = 2;
const wdpC = commands[i + 1] === '00' ? false : parseInt(commands[i + 1], 16);
const wdpUc = commands[i + 2] === '00' ? false : parseInt(commands[i + 2], 16);
data.watchDogParams = { wdpC, wdpUc };
break;
}
case '1f': {
command_len = 2;
data.overheatingThresholds = {
trigger: parseInt(commands[i + 1], 16),
recovery: parseInt(commands[i + 2], 16),
};
break;
}
case '5a': {
command_len = 1;
data.afterOverheatingProtectionRecovery = parseInt(commands[i + 1], 16);
break;
}
case '5c': {
command_len = 1;
data.ledIndicationMode = parseInt(commands[i + 1], 16);
break;
}
case '5d': {
command_len = 1;
data.manualChangeRelayState = parseInt(commands[i + 1], 16) === 0x01;
break;
}
case '5f': {
command_len = 1;
data.relayRecoveryState = parseInt(commands[i + 1], 16);
break;
}
case '60': {
command_len = 2;
data.overheatingEvents = {
events: parseInt(commands[i + 1], 16),
temperature: parseInt(commands[i + 2], 16),
};
break;
}
case '70': {
command_len = 2;
data.overheatingRecoveryTime = (parseInt(commands[i + 1], 16) << 8) | parseInt(commands[i + 2], 16);
break;
}
case 'b1': {
command_len = 1;
data.relayState = parseInt(commands[i + 1], 16) === 0x01;
break;
}
case 'a0': {
command_len = 4;
const fuota_address = parseInt(
`${commands[i + 1]}${commands[i + 2]}${commands[i + 3]}${commands[i + 4]}`,
16
);
const fuota_address_raw = `${commands[i + 1]}${commands[i + 2]}${commands[i + 3]}${commands[i + 4]}`;
data.fuota = { fuota_address, fuota_address_raw };
break;
}
case 'a4': {
command_len = 1;
data.region = parseInt(commands[i + 1], 16);
break;
}
default:
break;
}
commands.splice(i, command_len);
});

return data;
};

if (bytes[0] === 1) {
data = handleKeepalive(bytes, data);
} else {
data = handleResponse(bytes, data);
bytes = bytes.slice(-3);
data = handleKeepalive(bytes, data);
}

return { data };
} catch (e) {
console.log(e);
throw new Error('Unhandled data');
}
};
Binary file added vendor/mclimate/16ads.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
133 changes: 133 additions & 0 deletions vendor/mclimate/16ads.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
name: 16A Dry Switch (16ADS)
description: The МClimate 16ADS is a miniature device that features a 16A dry relay. The device is small enough to fit behind most wall switches and outlets. The device operates in LoRaWAN Class C, features FUOTA (Firmware Upgrades Over The Air) and has overheating protection

# Hardware versions (optional, use when you have revisions)
hardwareVersions:
- version: '1.0'
numeric: 1

# Firmware versions (at least one is mandatory)
firmwareVersions:
- # Firmware version
version: '1.0'
numeric: 1
hardwareVersions:
- '1.0'

# LoRaWAN Device Profiles per region
# Supported regions are EU863-870, US902-928, AU915-928, AS923, CN779-787, EU433, CN470-510, KR920-923, IN865-867, RU864-870
profiles:
EU863-870:
# Unique identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters)
id: 16ads-profile
lorawanCertified: false
codec: 16ads-codec

# Sensors that this device features (optional)
# Valid values are: accelerometer, altitude, auxiliary, barometer, battery, button, co2, distance, dust, gps, gyroscope,
# humidity, light, link, magnetometer, moisture, ph, pir, proximity, rssi, snr, sound, temperature, tvoc, velocity,
# vibration, water, wind direction and wind speed.
sensors:
- temperature
# Dimensions in mm (optional)
# Use width, height, length and/or diameter
dimensions:
width: 36
length: 18
height: 32

# Weight in grams (optional)
weight: 24

# Battery information (optional)
battery:
replaceable: false

# Operating conditions (optional)
operatingConditions:
# Temperature (Celsius)
temperature:
min: -10
max: 40
# Relative humidity (fraction of 1)
relativeHumidity:
min: 0.00
max: 0.80

# IP rating (optional)
ipCode: IP30

# Key provisioning (optional)
# Valid values are: custom (user can configure keys), join server and manifest.
keyProvisioning:
- custom
- manifest

# Key security (optional)
# Valid values are: none, read protected and secure element.
keySecurity: read protected

# Product and data sheet URLs (optional)
productURL: https://docs.mclimate.eu/mclimate-lorawan-devices/devices/mclimate-16a-dry-switch-16ads
dataSheetURL: https://3940008670-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-McDr-jr9h3qA888r1Yp%2Fuploads%2F4PSdg1EADYeBfci7DCmK%2FMClimate-16ADS-Datasheet.pdf?alt=media&token=8c95eed3-7cac-4859-855c-ba65ab3a6e5a
# resellerURLs:
# - name: 'Connected Things'
# region:
# - United Kingdom
# url: https://connectedthings.store/
# - name: 'Concept13'
# region:
# - United Kingdom
# url: https://www.concept13.co.uk
# - name: 'RG2i'
# region:
# - France
# url: https://connectedthings.store/
# - name: 'Wideco'
# region:
# - Sweden
# url: https://wideco.se
# - name: 'iioote'
# region:
# - Sweden
# url: https://iiooote.com

# Photos
photos:
main: 16aspm.png

# Regulatory compliances (optional)
compliances:
safety:
- body: IEC
norm: EN
standard: 62368-1:2020
- body: IEC
norm: EN
standard: 61010-1:2010
electromagneticCompatibility:
- body: ETSI
norm: EN
standard: 301489-1
version: 'latest'
- body: ETSI
norm: EN
standard: 301489-17
version: 'latest'
- body: CENELEC
norm: EN
standard: 55032:2015
- body: CENELEC
norm: EN
standard: 55035:2017
radioEquipment:
- body: ETSI
norm: EN
standard: 300220-1
- body: ETSI
norm: EN
standard: 300220-2
lowVoltageDirective:
- body: IEC
norm: EN
standard: 2014/35/EU
73 changes: 71 additions & 2 deletions vendor/mclimate/index.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,80 @@
endDevices:
- vicki
- t-valve
- flood-sensor
- vicki
- ht-sensor
- co2-sensor
- mc-button
- open-close
- wireless-thermostat
- co2-display
- co2-display-lite
- fan-coil-thermostat
- co2-display-lite
- 16aspm
- 16ads
profileIDs:
'0':
endDeviceID: 't-valve'
firmwareVersion: '6.0'
hardwareVersion: '2.3'
region: 'EU863-870'
'1':
endDeviceID: 'flood-sensor'
firmwareVersion: '6.0'
hardwareVersion: '2.4'
region: 'EU863-870'
'3':
endDeviceID: 'vicki'
firmwareVersion: '4.3'
hardwareVersion: '2.6'
region: 'EU863-870'
'4':
endDeviceID: 'ht-sensor'
firmwareVersion: '1.0'
hardwareVersion: '1.0'
region: 'EU863-870'
'5':
endDeviceID: 'co2-sensor'
firmwareVersion: '1.0'
hardwareVersion: '1.0'
region: 'EU863-870'
'6':
endDeviceID: 'mc-button'
firmwareVersion: '1.2'
hardwareVersion: '1.2'
region: 'EU863-870'
'7':
endDeviceID: 'open-close'
firmwareVersion: '1.2'
hardwareVersion: '1.3'
region: 'EU863-870'
'8':
endDeviceID: 'wireless-thermostat'
firmwareVersion: '1.5'
hardwareVersion: '3.0'
region: 'EU863-870'
'9':
endDeviceID: 'co2-display'
firmwareVersion: '1.1'
hardwareVersion: '2.6'
region: 'EU863-870'
'10':
endDeviceID: 'fan-coil-thermostat'
firmwareVersion: '1.0'
hardwareVersion: '1.1'
region: 'EU863-870'
'11':
endDeviceID: 'co2-display-lite'
firmwareVersion: '1.1'
hardwareVersion: '1.2'
region: 'EU863-870'
'13':
endDeviceID: '16aspm'
firmwareVersion: '1.2'
hardwareVersion: '1.3'
region: 'EU863-870'
'14':
endDeviceID: '16ads'
firmwareVersion: '1.0'
hardwareVersion: '1.0'
region: 'EU863-870'
13 changes: 13 additions & 0 deletions vendor/mclimate/mc-button-codec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
uplinkDecoder:
fileName: mc-button.js
examples:
- description: Short periodic uplink
input:
fPort: 2
bytes: [0x01, 0xAB, 0x02, 0x9B, 0x03]
output:
data:
sensorTemperature: 66.7
batteryVoltage: 3
thermistorProperlyConnected: true
pressEvent: 3
Loading

0 comments on commit b64c9ef

Please sign in to comment.