172 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
#!/command/with-contenv bashio
 | 
						|
# shellcheck shell=bash
 | 
						|
# ==============================================================================
 | 
						|
# Start mqtt service for disk only
 | 
						|
# ==============================================================================
 | 
						|
 | 
						|
readonly MAX_TIMEFRAME=60
 | 
						|
readonly MIN_TIMEFRAME=10
 | 
						|
readonly AVG_TIMEFRAME=$(((MAX_TIMEFRAME + MIN_TIMEFRAME) / 2))
 | 
						|
 | 
						|
if bashio::config.true "mqtt_nexgen_entities"; then
 | 
						|
    exec sleep infinity
 | 
						|
fi
 | 
						|
 | 
						|
if [ -f /root/.config/mosquitto_pub ]; then
 | 
						|
    bashio::log.info "Starting the MQTT daemon for disks info..."
 | 
						|
 | 
						|
    # Send autodiscovery entities
 | 
						|
    topic=$(bashio::config 'mqtt_topic')
 | 
						|
    if [ "$topic" = "null" ]; then topic="sambanas"; fi
 | 
						|
 | 
						|
    # Send discovery messages.
 | 
						|
    if ! bashio::config.true "autodiscovery.disable_persistent"; then prs="-r"; fi
 | 
						|
 | 
						|
    jdevice=$(jq -r -c -n --arg topic "$topic" --arg smbv "$(smbd -V | sed s/Version\ //)" --arg addon "$(bashio::addon.version)" '
 | 
						|
    {device:{
 | 
						|
        identifiers:[],
 | 
						|
        name: "SambaNas Physical Disk ",
 | 
						|
        hw_version: $addon,
 | 
						|
        sw_version: $smbv,
 | 
						|
        model: "SambaNas",
 | 
						|
        manufacturer: "@Dianlight",
 | 
						|
        via_device: $topic
 | 
						|
    }}')
 | 
						|
 | 
						|
    device_scan=$(smartctl --scan-open)
 | 
						|
 | 
						|
    if [ -z "$device_scan" ]; then
 | 
						|
        bashio::log.warning "No disk with S.M.A.R.T support found. Disable sensor report"
 | 
						|
        exec sleep infinity
 | 
						|
    fi
 | 
						|
 | 
						|
    while read -r -a device; do
 | 
						|
 | 
						|
        row=$(smartctl -A -l error -l selftest "${device[0]}" -j | jq '. * (.ata_smart_attributes.table // [] | INDEX(.name)) | del(.ata_smart_attributes.table)')
 | 
						|
        #bashio::log.info "2.2 ${row}"
 | 
						|
        for entity in device.name device.type device.protocol power_on_time.hours power_cycle_count temperature.current \
 | 
						|
            Raw_Read_Error_Rate.raw.value Reallocated_Sector_Ct.raw.value Wear_Leveling_Count.raw.value UDMA_CRC_Error_Count.raw.value \
 | 
						|
            ata_smart_error_log.summary.count ata_smart_self_test_log.standard.count; do
 | 
						|
 | 
						|
            if [[ -z $(jq ".$entity // empty" <<<"$row") ]]; then
 | 
						|
                #      bashio::log.info "2.2 Missing ${entity} in ${row}"
 | 
						|
                continue
 | 
						|
            fi
 | 
						|
 | 
						|
            exmsg={}
 | 
						|
            etype=""
 | 
						|
 | 
						|
            base=$(jq --arg topic "$topic" --arg entity "$entity" '
 | 
						|
                    {
 | 
						|
                        name:($topic+" "+$entity +" "+.device.info_name),
 | 
						|
                        unique_id:((.device.name | explode | join("")) + "-" + ($entity|explode|join(""))),
 | 
						|
                        value_template:("{{ value_json." +$entity+ "}}"),
 | 
						|
                        state_topic:($topic + "/" + (.device.name | gsub("[^A-z]";"")) + "/state" ),
 | 
						|
                        oth:{
 | 
						|
                                uuid:.device.name | explode | join(""),
 | 
						|
                                label:.device.name
 | 
						|
                            }
 | 
						|
                    }' <<<"$row")
 | 
						|
 | 
						|
            case "$entity" in
 | 
						|
            device.name | device.type | device.protocol) #TEXT
 | 
						|
                etype="sensor"
 | 
						|
                exmsg=$(jq --arg topic "$topic" --arg entity "$entity" '
 | 
						|
                    {
 | 
						|
                        mode: "text",
 | 
						|
                        icon:"mdi:harddisk"
 | 
						|
                    }' <<<"$row")
 | 
						|
                ;;
 | 
						|
            power_on_time.hours) #Time
 | 
						|
                etype="sensor"
 | 
						|
                exmsg=$(jq --arg topic "$topic" --arg entity "$entity" '
 | 
						|
                    {
 | 
						|
                        unit_of_measurement: "h",
 | 
						|
                        device_class: "duration"
 | 
						|
                    }' <<<"$row")
 | 
						|
                ;;
 | 
						|
            power_cycle_count) #number
 | 
						|
                etype="sensor"
 | 
						|
                exmsg=$(jq --arg topic "$topic" --arg entity "$entity" '
 | 
						|
                    {
 | 
						|
                        _unit_of_measurement: "",
 | 
						|
                        icon:"mdi:power-cycle"
 | 
						|
                    }' <<<"$row")
 | 
						|
                ;;
 | 
						|
            Raw_Read_Error_Rate.raw.value | Reallocated_Sector_Ct.raw.value | Wear_Leveling_Count.raw.value | UDMA_CRC_Error_Count.raw.value | ata_smart_error_log.summary.count | ata_smart_self_test_log.standard.count) #number
 | 
						|
                etype="sensor"
 | 
						|
                exmsg=$(jq --arg topic "$topic" --arg entity "$entity" '
 | 
						|
                    {
 | 
						|
                        _unit_of_measurement: "",
 | 
						|
                        icon:"mdi:chart-box-outline"
 | 
						|
                    }' <<<"$row")
 | 
						|
                ;;
 | 
						|
            temperature.current) #temperature
 | 
						|
                etype="sensor"
 | 
						|
                exmsg=$(jq --arg topic "$topic" --arg entity "$entity" '
 | 
						|
                    {
 | 
						|
                        unit_of_measurement: "°C",
 | 
						|
                        device_class: "temperature",
 | 
						|
                        _icon:"mdi:thermometer"
 | 
						|
                    }' <<<"$row")
 | 
						|
                ;;
 | 
						|
            *)
 | 
						|
                bashio::log.warning "Autodiscovery for $entity missing!"
 | 
						|
                ;;
 | 
						|
            esac
 | 
						|
            #bashio::log.info "2.4 $base $exmsg"
 | 
						|
            msg=$(echo "$base" "$jdevice" "$exmsg" | jq -s 'add|.device.identifiers[.device.identifiers|length]=.oth.uuid|.device.name=(.device.name + .oth.label)|del(.oth)')
 | 
						|
            #bashio::log.debug "$msg"
 | 
						|
            mosquitto_pub "${prs}" -t "homeassistant/${etype}/${topic}/$(jq -r '.device.name | explode | join("")' <<<$row)-${entity//[\.\/]/-}/config" -m "$msg"
 | 
						|
        done
 | 
						|
 | 
						|
        #  bashio::log.info "2.3"
 | 
						|
 | 
						|
    done <<<"${device_scan}"
 | 
						|
 | 
						|
    while read -r -a device; do
 | 
						|
        mkfifo /tmp/mqtt-hanlder-${device[0]//\//}
 | 
						|
        # Send status message process
 | 
						|
        tail -F /tmp/mqtt-hanlder-${device[0]//\//} | mosquitto_pub -l -t "${topic}/${device[0]//\//}/state" &
 | 
						|
    done <<<"${device_scan}"
 | 
						|
 | 
						|
    while read -r -a device; do
 | 
						|
        cdevice=${device[0]//\//}
 | 
						|
        shaOldMessage="-"
 | 
						|
        sleepTime=$AVG_TIMEFRAME
 | 
						|
        while true; do
 | 
						|
            #bashio::log.info "[$cdevice] ${shaOldMessage} $sleepTime"
 | 
						|
            status=$(smartctl -A -l error -l selftest "${device[0]}" -j | jq -c '. * (.ata_smart_attributes.table // [] | INDEX(.name)) | del(.ata_smart_attributes.table) | del(.local_time) | del(.smartctl) | del (.json_format_version)')
 | 
						|
            # Debug
 | 
						|
            shaMessage=$(sha1sum <<<"$status")
 | 
						|
            # bashio::log.green "[$cdevice] SleepTimes: $sleepTime $shaOldMessage] ${status}"
 | 
						|
            if [ "${shaOldMessage}" = "$shaMessage" ]; then
 | 
						|
                sleepTime=$((sleepTime * 2))
 | 
						|
                [ ${sleepTime} -gt $MAX_TIMEFRAME ] && sleepTime=$MAX_TIMEFRAME
 | 
						|
            else
 | 
						|
                # Send status message
 | 
						|
                if [ $sleepTime -gt $AVG_TIMEFRAME ]; then
 | 
						|
                    sleepTime=$((sleepTime / 2))
 | 
						|
                else
 | 
						|
                    sleepTime=$((sleepTime - MIN_TIMEFRAME))
 | 
						|
                fi
 | 
						|
                [ $sleepTime -le $MIN_TIMEFRAME ] && sleepTime=$MIN_TIMEFRAME
 | 
						|
            fi
 | 
						|
            jq -c --arg st "$sleepTime" --arg sh "$shaMessage" '. +
 | 
						|
                {
 | 
						|
                    ref: {
 | 
						|
                        mws: $st,
 | 
						|
                        sha: $sh
 | 
						|
                    }
 | 
						|
                }' <<<"${status}" >/tmp/mqtt-hanlder-$cdevice
 | 
						|
            shaOldMessage=$shaMessage
 | 
						|
            # Sleep
 | 
						|
            sleep ${sleepTime}
 | 
						|
        done &
 | 
						|
        sleep $((10 / $(wc -l <<<"$device_scan")))
 | 
						|
    done <<<"${device_scan}"
 | 
						|
    wait
 | 
						|
else
 | 
						|
    exec sleep infinity
 | 
						|
fi
 |