// Copyright (C) 2020-2026 Fredrik Öhrström (gpl-3.0-or-later)
driver {
name = ei6500
meter_type = SmokeDetector
default_fields = name,id,status,last_alarm_date,alarm_counter,timestamp
detect {
mvt = EIE,0c,1a
}
library {
use = software_version
}
mfct_tpl_status_bits {
mask_bits = 0xe0
default_message = OK
map {
name = RTC_INVALID
value = 0x40
test = set
}
}
fields {
field {
name = status
quantity = Text
info = 'Meter error flags. IMPORTANT! Smoke alarm is NOT reported here! You MUST check last alarm date and counter!'
attributes = STATUS,INCLUDE_TPL_STATUS
default_message = OK
match {
measurement_type = Instantaneous
vif_range = ErrorFlags
}
lookup {
name = ERROR_FLAGS
map_type = BitToString
mask_bits = 0xffff
default_message = OK
/* bits 0-7: not used (lower byte)
bit 8 (0x0100): not used
bit 9 (0x0200): application error, unknown field C
bit 10 (0x0400): application error, unknown field CI
bit 11 (0x0800): application error, unknown record
bit 12 (0x1000): application error, access right
bit 13 (0x2000): application error, record size
bit 14 (0x4000): application error, record value
bit 15 (0x8000): application error, bad password */
map {
name = UNKNOWN_FIELD_C
value = 0x0200
test = Set
}
map {
name = UNKNOWN_FIELD_CI
value = 0x0400
test = Set
}
map {
name = UNKNOWN_RECORD
value = 0x0800
test = Set
}
map {
name = ACCESS_RIGHT
value = 0x1000
test = Set
}
map {
name = RECORD_SIZE
value = 0x2000
test = Set
}
map {
name = RECORD_VALUE
value = 0x4000
test = Set
}
map {
name = BAD_PASSWORD
value = 0x8000
test = Set
}
}
}
field {
name = last_alarm
quantity = PointInTime
info = 'Date when the smoke alarm last triggered.'
display_unit = DateLT
match {
measurement_type = Instantaneous
vif_range = Date
tariff_nr = 1
subunit_nr = 1
}
}
field {
name = alarm
quantity = Dimensionless
info = 'Number of times the smoke alarm has triggered.'
match {
measurement_type = Instantaneous
vif_range = CumulationCounter
tariff_nr = 1
subunit_nr = 1
}
}
field {
name = message
quantity = PointInTime
info = 'Device date time.'
match {
measurement_type = Instantaneous
vif_range = DateTime
}
}
field {
name = duration_removed
quantity = Time
info = 'Time the smoke alarm has been removed.'
match {
measurement_type = Instantaneous
vif_range = DurationOfTariff
tariff_nr = 2
subunit_nr = 1
}
}
field {
name = last_remove
quantity = PointInTime
info = 'Date when the smoke alarm was last removed.'
display_unit = DateLT
match {
measurement_type = Instantaneous
vif_range = Date
tariff_nr = 2
subunit_nr = 1
}
}
field {
name = removed
quantity = Dimensionless
info = 'Number of times the smoke alarm has been removed.'
match {
measurement_type = Instantaneous
vif_range = CumulationCounter
subunit_nr = 1
tariff_nr = 2
}
}
field {
name = test_button_last
quantity = PointInTime
info = 'Date when test button was last pressed.'
display_unit = DateLT
match {
measurement_type = Instantaneous
vif_range = Date
subunit_nr = 1
tariff_nr = 3
}
}
field {
name = test_button
quantity = Dimensionless
info = 'Number of times the test button has been pressed.'
match {
measurement_type = Instantaneous
vif_range = CumulationCounter
subunit_nr = 1
tariff_nr = 3
}
}
field {
name = installation
quantity = PointInTime
info = 'Date when the smoke alarm was installed.'
display_unit = DateLT
match {
measurement_type = Instantaneous
vif_range = Date
tariff_nr = 2
}
}
field {
name = last_sound_check
quantity = PointInTime
info = 'Date when the smoke alarm last checked the piezo speaker.'
display_unit = DateLT
match {
measurement_type = Instantaneous
vif_range = Date
storage_nr = 1
}
}
field {
name = ei_head_raw
quantity = Dimensionless
attributes = HIDE
vif_scaling = None
dif_signedness = Unsigned
match {
difvifkey = 8440FF2C
}
}
field {
name = dust_level
quantity = Text
attributes = DEPRECATED
info = 'Dust level 0 (best) to 31 (worst). Deprecated. Use dust_level_counter instead.'
match {
difvifkey = 8440FF2C
}
lookup {
name = DUST
map_type = IndexToString
mask_bits = 0x1f
// We use the default mapping of bits to DUST_1 DUST_2 DUST_3 etc, which happens since there are no map rules here.
}
}
field {
name = dust_level
quantity = Dimensionless
info = 'Dust level 0 (best) to 31 (worst). Recommend cleaning when level exceeds 28.'
calculate = 'ei_head_raw_counter & 31counter'
}
field {
name = dust_status
quantity = Text
info = 'Status of smoke detector sensors, merged into the status field.'
attributes = INJECT_INTO_STATUS,HIDE
match {
difvifkey = 8440FF2C
}
lookup {
name = DUST_STATUS
map_type = IndexToString
mask_bits = 0x0000001c
default_message = ''
map {
name = ''
value = 0x00000000
test = Set
}
map {
name = ''
value = 0x00000004
test = Set
}
map {
name = ''
value = 0x00000008
test = Set
}
map {
name = ''
value = 0x0000000c
test = Set
}
map {
name = ''
value = 0x00000010
test = Set
}
map {
name = ''
value = 0x00000014
test = Set
}
map {
name = ''
value = 0x00000018
test = Set
}
map {
name = CLEANING_RECOMMENDED
value = 0x0000001c
test = Set
}
}
}
field {
name = battery_level
quantity = Text
info = 'Battery voltage level.'
match {
difvifkey = 8440FF2C
}
lookup {
name = BATTERY_VOLTAGE
map_type = IndexToString
mask_bits = 0x0f00
default_message = 2.25V
map {
name = 2.25V
value = 0x0000
test = Set
}
map {
name = 2.30V
value = 0x0100
test = Set
}
map {
name = 2.35V
value = 0x0200
test = Set
}
map {
name = 2.40V
value = 0x0300
test = Set
}
map {
name = 2.45V
value = 0x0400
test = Set
}
map {
name = 2.50V
value = 0x0500
test = Set
}
map {
name = 2.55V
value = 0x0600
test = Set
}
map {
name = 2.60V
value = 0x0700
test = Set
}
map {
name = 2.65V
value = 0x0800
test = Set
}
map {
name = 2.70V
value = 0x0900
test = Set
}
map {
name = 2.75V
value = 0x0a00
test = Set
}
map {
name = 2.80V
value = 0x0b00
test = Set
}
map {
name = 2.85V
value = 0x0c00
test = Set
}
map {
name = 2.90V
value = 0x0d00
test = Set
}
map {
name = 2.95V
value = 0x0e00
test = Set
}
map {
name = 3.00V
value = 0x0f00
test = Set
}
}
}
field {
name = obstacle_distance
quantity = Text
info = 'The distance to a detected obstacle.'
match {
difvifkey = 8440FF2C
}
lookup {
name = OBSTACLE_DISTANCE
map_type = IndexToString
mask_bits = 0x700000
default_message = ''
map {
name = SEODS_NOT_COMPLETED
value = 0x000000
test = Set
}
map {
name = ''
value = 0x100000
test = Set
}
map {
name = 45_TO_60_CM
value = 0x200000
test = Set
}
map {
name = 38_TO_53_CM
value = 0x300000
test = Set
}
map {
name = 33_TO_48_CM
value = 0x400000
test = Set
}
map {
name = 28_TO_40_CM
value = 0x500000
test = Set
}
map {
name = 20_TO_33_CM
value = 0x600000
test = Set
}
map {
name = 0_TO_25_CM
value = 0x700000
test = Set
}
}
}
field {
name = head_status
quantity = Text
info = 'Status of smoke detector sensors, merged into the status field.'
attributes = INJECT_INTO_STATUS,HIDE
match {
difvifkey = 8440FF2C
}
lookup {
name = HEAD_STATUS
map_type = BitToString
mask_bits = 0xff8ff0e0
// 0x00000000-0x000001f dust level
map {
name = SOUNDER_FAULT
value = 0x00000020
test = Set
}
map {
name = TAMPER_WHILE_REMOVED
value = 0x00000040
test = Set
}
map {
name = EOL_REACHED
value = 0x00000080
test = Set
}
// 0x00000100-0x000f00 battery level
map {
name = LOW_BATTERY_FAULT
value = 0x00001000
test = Set
}
map {
name = ALARM_SENSOR_FAULT
value = 0x00002000
test = Set
}
map {
name = OBSTACLE_DETECTOR_FAULT
value = 0x00004000
test = Set
}
map {
name = EOL_WITHIN_12_MONTH
value = 0x00008000
test = Set
}
map {
name = SEODS_NOT_YET_COMPLETED
value = 0x00010000
test = NotSet
}
map {
name = ENV_CHANGED_SINCE_INSTALLATION
value = 0x00020000
test = Set
}
map {
name = COMM_TO_HEAD_FAULT
value = 0x00040000
test = Set
}
map {
name = INTERFERENCE_PREVENTING_OBSTACLE_DETECTION
value = 0x00080000
test = Set
}
// 0x00100000-0x0700000 distance
// 0x00800000 reserved
map {
name = OBSTACLE_DETECTED
value = 0x01000000
test = Set
}
map {
name = SMOKE_DETECTOR_FULLY_COVERED
value = 0x02000000
test = Set
}
}
}
}
tests {
test {
args = 'Smokey1 ei6500 01097274 NOKEY'
telegram = 58442515747209010C1A7A8B0000000BFD0F070101046D2A06D82502FD17000082206CD825426CD0238440FF2C000F11008250FD61000082506C01018260FD6100008360FD3100000082606C01018270FD61000082706C0101
json = '{"_":"telegram","media":"smoke detector","meter":"ei6500","name":"Smokey1","id":"01097274","status":"OK","last_alarm_date":"2000-01-01","alarm_counter":0,"software_version":"010107","message_datetime":"2022-05-24 06:42","duration_removed_h":0,"last_remove_date":"2000-01-01","removed_counter":0,"test_button_last_date":"2000-01-01","test_button_counter":0,"installation_date":"2022-05-24","last_sound_check_date":"2022-03-16","dust_level": "DUST_0","dust_level_counter":0,"battery_level":"3.00V","obstacle_distance":"","timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Smokey1;01097274;OK;2000-01-01;0;1111-11-11 11:11.11'
}
test {
args = 'Smokey2 ei6500 01097274 NOKEY'
telegram = 58442515747209010C1A7A8D0000000BFD0F070101046D2E06D82502FD17000082206CD825426CD0238440FF2C000F11008250FD61000082506C01018260FD6100008360FD3100000082606C01018270FD61020082706CD825
json = '{"_":"telegram","media":"smoke detector","meter":"ei6500","name":"Smokey2","id":"01097274","status":"OK","last_alarm_date":"2000-01-01","alarm_counter":0,"software_version":"010107","message_datetime":"2022-05-24 06:46","duration_removed_h":0,"last_remove_date":"2000-01-01","removed_counter":0,"test_button_last_date":"2022-05-24","test_button_counter":2,"installation_date":"2022-05-24","last_sound_check_date":"2022-03-16","dust_level": "DUST_0","dust_level_counter":0,"battery_level":"3.00V","obstacle_distance":"","timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Smokey2;01097274;OK;2000-01-01;0;1111-11-11 11:11.11'
}
test {
args = 'Smokey3 ei6500 01097274 NOKEY'
telegram = 58442515747209010C1A7A900000000BFD0F070101046D3406D82502FD17000082206CD825426CD0238440FF2C020F11008250FD61010082506CD8258260FD6100008360FD3100000082606C01018270FD61020082706CD825
json = '{"_":"telegram","media":"smoke detector","meter":"ei6500","name":"Smokey3","id":"01097274","status":"OK","last_alarm_date":"2022-05-24","alarm_counter":1,"software_version":"010107","message_datetime":"2022-05-24 06:52","duration_removed_h":0,"last_remove_date":"2000-01-01","removed_counter":0,"test_button_last_date":"2022-05-24","test_button_counter":2,"installation_date":"2022-05-24","last_sound_check_date":"2022-03-16","dust_level": "DUST_2","dust_level_counter":2,"battery_level":"3.00V","obstacle_distance":"","timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Smokey3;01097274;OK;2022-05-24;1;1111-11-11 11:11.11'
}
test {
args = 'Smokey4 ei6500 01097274 NOKEY'
telegram = 58442515747209010C1A7A940000000BFD0F070101046D0007D82502FD17000082206CD825426CD0238440FF2C420F11008250FD61010082506CD8258260FD6101008360FD3101000082606CD8258270FD61020082706CD825
json = '{"_":"telegram","media":"smoke detector","meter":"ei6500","name":"Smokey4","id":"01097274","status":"TAMPER_WHILE_REMOVED","last_alarm_date":"2022-05-24","alarm_counter":1,"software_version":"010107","message_datetime":"2022-05-24 07:00","duration_removed_h":0.016667,"last_remove_date":"2022-05-24","removed_counter":1,"test_button_last_date":"2022-05-24","test_button_counter":2,"installation_date":"2022-05-24","last_sound_check_date":"2022-03-16","dust_level": "DUST_2","dust_level_counter":2,"battery_level":"3.00V","obstacle_distance":"","timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Smokey4;01097274;TAMPER_WHILE_REMOVED;2022-05-24;1;1111-11-11 11:11.11'
}
test {
comment = 'Synthetic telegram: dust level 27, no cleaning recommendation yet.'
args = 'Smokey5 ei6500 01097274 NOKEY'
telegram = 58442515747209010C1A7A8B0000000BFD0F070101046D2A06D82502FD17000082206CD825426CD0238440FF2C1b0F11008250FD61000082506C01018260FD6100008360FD3100000082606C01018270FD61000082706C0101
json = '{"_":"telegram","media":"smoke detector","meter":"ei6500","name":"Smokey5","id":"01097274","status":"OK","last_alarm_date":"2000-01-01","alarm_counter":0,"software_version":"010107","message_datetime":"2022-05-24 06:42","duration_removed_h":0,"last_remove_date":"2000-01-01","removed_counter":0,"test_button_last_date":"2000-01-01","test_button_counter":0,"installation_date":"2022-05-24","last_sound_check_date":"2022-03-16","dust_level": "DUST_1B","dust_level_counter":27,"battery_level":"3.00V","obstacle_distance":"","timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Smokey5;01097274;OK;2000-01-01;0;1111-11-11 11:11.11'
}
test {
comment = 'Synthetic telegram: dust level 28, cleaning is recommended.'
args = 'Smokey6 ei6500 01097274 NOKEY'
telegram = 58442515747209010C1A7A8B0000000BFD0F070101046D2A06D82502FD17000082206CD825426CD0238440FF2C1c0F11008250FD61000082506C01018260FD6100008360FD3100000082606C01018270FD61000082706C0101
json = '{"_":"telegram","media":"smoke detector","meter":"ei6500","name":"Smokey6","id":"01097274","status":"CLEANING_RECOMMENDED","last_alarm_date":"2000-01-01","alarm_counter":0,"software_version":"010107","message_datetime":"2022-05-24 06:42","duration_removed_h":0,"last_remove_date":"2000-01-01","removed_counter":0,"test_button_last_date":"2000-01-01","test_button_counter":0,"installation_date":"2022-05-24","last_sound_check_date":"2022-03-16","dust_level": "DUST_1C","dust_level_counter":28,"battery_level":"3.00V","obstacle_distance":"","timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Smokey6;01097274;CLEANING_RECOMMENDED;2000-01-01;0;1111-11-11 11:11.11'
}
}
}