{"id":46638231,"url":"https://github.com/tetherto/miningos-wrk-sensor-temp-seneca","last_synced_at":"2026-03-08T02:13:13.438Z","repository":{"id":340876427,"uuid":"1129676790","full_name":"tetherto/miningos-wrk-sensor-temp-seneca","owner":"tetherto","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-26T23:02:56.000Z","size":84,"stargazers_count":0,"open_issues_count":0,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-27T05:35:04.186Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tetherto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-07T12:29:36.000Z","updated_at":"2026-02-26T23:03:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tetherto/miningos-wrk-sensor-temp-seneca","commit_stats":null,"previous_names":["tetherto/miningos-wrk-sensor-temp-seneca"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/tetherto/miningos-wrk-sensor-temp-seneca","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tetherto%2Fminingos-wrk-sensor-temp-seneca","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tetherto%2Fminingos-wrk-sensor-temp-seneca/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tetherto%2Fminingos-wrk-sensor-temp-seneca/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tetherto%2Fminingos-wrk-sensor-temp-seneca/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tetherto","download_url":"https://codeload.github.com/tetherto/miningos-wrk-sensor-temp-seneca/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tetherto%2Fminingos-wrk-sensor-temp-seneca/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30242406,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T00:58:18.660Z","status":"online","status_checked_at":"2026-03-08T02:00:06.215Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-08T02:13:12.782Z","updated_at":"2026-03-08T02:13:13.419Z","avatar_url":"https://github.com/tetherto.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# miningos-wrk-sensor-temp-seneca\n\nWorker for SENECA temperature sensors in Bitcoin mining infrastructure, providing real-time temperature monitoring for mining equipment. This worker interfaces with SENECA temperature sensors using the Modbus TCP protocol. It collects temperature readings from configurable holding registers, processes the data, stores it in a distributed database (Hyperbee), and updates it to the mining network.\n\n## Table of Contents\n\n1. [Overview](#overview)\n2. [Introduction](#introduction)\n3. [Setup](#setup)\n4. [Configuration](#configuration)\n5. [API Reference](#api-reference)\n6. [Mock Server](#mock-server)\n7. [Alert System](#alert-system)\n\n## Overview\n\nThe SENECA temperature sensor worker is part of the MiningOS mining infrastructure ecosystem. It provides:\n\n- **Real-time temperature monitoring** via Modbus TCP protocol\n- **Alert management** for critical temperature thresholds\n- **Historical data collection** with configurable intervals\n- **Device management** through RPC interface\n- **Mock server support** for testing and development\n\n### Use Cases\n\n- Monitor transformer oil temperature\n- Track electrical cabinet temperatures\n- Oversee mining equipment thermal conditions\n- Trigger alerts on temperature anomalies\n\n## Setup\n\n### Prerequisites\n\n```bash\nnode \u003e= 20.0\n```\n\n### Installation\n\n1. Clone the repository:\n```bash\ngit clone https://github.com/tetherto/miningos-wrk-sensor-temp-seneca.git\ncd miningos-wrk-sensor-temp-seneca\n```\n\n2. Install dependencies:\n```bash\nnpm install\n```\n\n3. Setup configuration files:\n```bash\nbash setup-config.sh\n```\n\nThis creates configuration files from examples:\n- `config/base.thing.json` (worker settings)\n- `config/common.json` (logging and debug)\n- `config/facs/net.config.json` (network settings)\n- `config/facs/store.config.json` (storage settings)\n\n## Configuration\n\n### Base Configuration\n\n**File:** `config/base.thing.json.example`\n\nThe base configuration file controls sensor polling behavior, logging, and alert thresholds. After setup, copy this file to `config/base.thing.json` for use.\n\n```json\n{\n  \"collectSnapTimeoutMs\": 10000,\n  \"collectSnapsItvMs\": 10000,\n  \"logRotateMaxLength\": 10000,\n  \"logKeepCount\": 3,\n  \"alerts\": {\n    \"sensor-temp-seneca\": {\n      \"cabinet_temp_high\": {\n        \"description\": \"LV Cabinet temperature is above 60 degrees.\",\n        \"severity\": \"high\",\n        \"params\": {\n          \"temp\": 60\n        }\n      },\n      \"cabinet_temp_alert\": {\n        \"description\": \"LV Cabinet temperature is above 70 degrees.\",\n        \"severity\": \"critical\",\n        \"params\": {\n          \"temp\": 70\n        }\n      },\n      \"oil_temp_high\": {\n        \"description\": \"Transformer oil temperature is above 80 degrees.\",\n        \"severity\": \"high\",\n        \"params\": {\n          \"temp\": 80\n        }\n      },\n      \"oil_temp_critical\": {\n        \"description\": \"Transformer oil temperature is above 90 degrees. Transformer will trip at 95 degrees.\",\n        \"severity\": \"critical\",\n        \"params\": {\n          \"temp\": 90\n        }\n      },\n      \"sensor_error\": {\n        \"description\": \"Sensor reading is faulty\",\n        \"severity\": \"medium\"\n      }\n    }\n  },\n  \"sensor\": {\n    \"timeout\": 10000\n  }\n}\n```\n\n#### Core Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `collectSnapTimeoutMs` | number | 10000 | Maximum time to wait for sensor reading before timeout (10 seconds) |\n| `collectSnapsItvMs` | number | 10000 | Interval for collecting sensor snapshots (10 seconds) |\n| `logRotateMaxLength` | number | 10000 | Maximum number of entries before log rotation |\n| `logKeepCount` | number | 3 | Number of rotated log files to retain |\n| `sensor.timeout` | number | 10000 | Modbus communication timeout in milliseconds (10 seconds) |\n\n#### Understanding Configuration Timing\n\nThe Seneca worker inherits from the thing template, which provides several timing-related configuration options. Here's how they work together:\n\n**Collection Cycle:** Every `collectSnapsItvMs` milliseconds, the worker attempts to read all registered sensors. Each individual sensor read must complete within `collectSnapTimeoutMs` or it times out.\n\n**Storage Behavior:** Sensor readings are stored to the database at an interval controlled by `storeSnapItvMs`, which defaults to 300000 milliseconds (5 minutes) if not specified in the configuration. This means sensors are polled every 10 seconds, but only persisted to storage every 5 minutes to reduce disk I/O.\n\n**Real-time Data:** Despite the storage interval, the most recent reading is always cached in memory and available immediately through the `getRealtimeData()` method, which is polled every 10 seconds as defined by the sensor template's real-time data schedule.\n\n### Alert Configuration\n\nThe alert system monitors temperature thresholds and generates notifications when limits are exceeded. Alerts are position-aware, meaning different thresholds apply based on sensor location.\n\n#### Alert Types\n\n| Alert Type | Applies To | Severity | Description |\n|------------|-----------|----------|-------------|\n| `cabinet_temp_high` | Cabinet sensors (position starts with 'lv') | high | Warning level for electrical cabinet temperature |\n| `cabinet_temp_alert` | Cabinet sensors (position starts with 'lv') | critical | Critical level for electrical cabinet temperature |\n| `oil_temp_high` | Transformer sensors (position starts with 'tr') | high | Warning level for transformer oil temperature |\n| `oil_temp_critical` | Transformer sensors (position starts with 'tr') | critical | Critical level approaching transformer trip point |\n| `sensor_error` | All sensors | medium | Sensor communication or reading failure |\n\n#### Alert Conditions\n\nAlerts are triggered when specific conditions are met. The alert system examines each sensor reading and applies rules based on the sensor's position property:\n\n**Cabinet Alerts:** These alerts activate for sensors whose position information ends with a segment starting with \"lv\" (low voltage). For example, a position like \"rack-1_row-2_lv-cabinet-3\" would trigger cabinet alerts. The system checks if the temperature exceeds the configured threshold and that the reading is valid (not the error value of 850°C).\n\n**Transformer Oil Alerts:** These alerts activate for sensors whose position ends with a segment starting with \"tr\" (transformer). For example, \"facility-north_transformer-1_tr-oil-temp\" would trigger oil temperature alerts. Transformer oil has different thermal characteristics than air, so separate thresholds are appropriate.\n\n**Sensor Error Alert:** This alert triggers automatically when the sensor returns a reading of 850.0°C, which is the Seneca's indicator for a faulty or disconnected probe.\n\n#### Customizing Alert Thresholds\n\nYou can modify alert thresholds to match your facility's requirements. Temperature values are in degrees Celsius:\n\n```json\n{\n  \"alerts\": {\n    \"sensor-temp-seneca\": {\n      \"cabinet_temp_high\": {\n        \"description\": \"Custom description for high cabinet temperature\",\n        \"severity\": \"high\",\n        \"params\": {\n          \"temp\": 55\n        }\n      }\n    }\n  }\n}\n```\n\n### Sensor Registration\n\nSensors are registered dynamically via RPC calls. Each sensor requires connection parameters that tell the worker how to communicate via Modbus TCP.\n\n#### Registration Parameters\n\n```javascript\n{\n  \"id\": \"sensor-cabinet-north-1\",     // Unique sensor identifier\n  \"info\": {\n    \"pos\": \"rack-1_row-2_lv-cabinet\"  // Position for alert routing\n  },\n  \"opts\": {\n    \"address\": \"192.168.1.100\",       // Sensor IP address\n    \"port\": 502,                       // Modbus TCP port\n    \"unitId\": 1,                       // Modbus unit/slave ID\n    \"register\": 3                      // Holding register address\n  }\n}\n```\n\n#### Connection Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `address` | string | Yes | IP address or hostname of the Seneca sensor |\n| `port` | number | Yes | Modbus TCP port number (typically 502) |\n| `unitId` | number | Yes | Modbus unit/slave identifier (typically 0 or 1) |\n| `register` | number | Yes | Holding register address to read temperature from (typically 2-5) |\n\n#### Position Naming Convention\n\nThe position string in the `info` object determines which alerts apply to the sensor. Use these patterns:\n\n- **Cabinet sensors:** End position with `lv-cabinet-X` or similar segment starting with \"lv\"\n- **Transformer sensors:** End position with `tr-oil-X` or similar segment starting with \"tr\"\n\nExample positions:\n- `facility-a_rack-1_row-2_lv-cabinet-3`\n- `facility-a_transformer-1_tr-oil-temp`\n- `building-north_electrical-room-1_lv-panel-main`\n\n#### Register Address Mapping\n\nSeneca temperature sensors expose multiple temperature channels on consecutive holding registers. The Seneca Z-4RTD unit provides four temperature inputs on registers 2 through 5:\n\n| Register | Channel | Description |\n|----------|---------|-------------|\n| 2 | Input 1 | First RTD temperature sensor |\n| 3 | Input 2 | Second RTD temperature sensor |\n| 4 | Input 3 | Third RTD temperature sensor |\n| 5 | Input 4 | Fourth RTD temperature sensor |\n\nWhen you register a sensor, specify which register (2-5) corresponds to the physical sensor location you want to monitor.\n\n#### Temperature Data Format\n\nThe Seneca returns temperature values as unsigned 16-bit integers in tenths of degrees Celsius. The worker automatically converts these to decimal degrees:\n\n- Raw value: `235` → Converted value: `23.5°C`\n- Raw value: `1050` → Converted value: `105.0°C`\n- Raw value: `8500` → Converted value: `850.0°C` (error condition)\n\n### Network Configuration\n\n**File:** `config/facs/net.config.json.example`\n\nThis configuration controls RPC access permissions:\n\n```json\n{\n  \"r0\": {\n    \"allow\": [],\n    \"allowLocal\": true\n  }\n}\n```\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `allow` | array | [] | List of allowed RPC public keys (empty = allow none) |\n| `allowLocal` | boolean | true | Allow connections from localhost |\n\n#### Security Considerations\n\nIn production environments, you should populate the `allow` array with specific RPC public keys of authorized clients and set `allowLocal` to false if remote access is required. The worker generates its own RPC public key on startup, which can be found in the status file at `status/wrk-sensor-rack-temp-seneca-{rack-name}.json`.\n\n### Additional Configuration Files\n\n#### Common Configuration\n\n**File:** `config/common.json.example`\n\n```json\n{\n  \"dir_log\": \"logs\",\n  \"debug\": 0\n}\n```\n\nThis file controls logging directory and debug level settings inherited from the base worker framework.\n\n#### Store Configuration\n\n**File:** `config/facs/store.config.json.example`\n\n```json\n{}\n```\n\nThis empty configuration uses default storage settings. The worker automatically creates storage in the `store/{rack-name}` directory.\n\n## API Reference\n\n### RPC Methods\n\nAll RPC methods are called via the Hyperswarm RPC interface. You can use the `hp-rpc-cli` command-line tool for manual testing, or integrate programmatically through the Hyperswarm RPC client libraries.\n\n#### Getting Started: Obtaining the Worker's RPC Public Key\n\nBefore you can call any RPC methods, you need to know the worker's public key. This key is automatically generated when the worker starts and is saved in a status file. Here's how to find it:\n\n**Step 1:** Start your Seneca sensor worker for a specific rack. For example, to start a worker for rack zero:\n\n```bash\nnode worker.js --wtype wrk-sensor-rack-temp-seneca --env development --rack rack-0\n```\n\n**Step 2:** Once the worker is running, locate its status file. The file will be named according to the pattern: `status/wrk-sensor-rack-temp-seneca-{rack-name}.json`\n\nFor our example, this would be:\n```bash\ncat status/wrk-sensor-rack-temp-seneca-rack-0.json\n```\n\n**Step 3:** Extract the `rpcPublicKey` field from the JSON output. This is a hexadecimal string that uniquely identifies your worker on the network. You'll use this value in all subsequent RPC calls.\n\n---\n\n#### registerThing\n\nWhen you register a sensor, you're essentially telling a worker process about a new device it should monitor. The worker will then attempt to connect to that Seneca sensor using the Modbus protocol and begin collecting temperature readings at regular intervals.\n\nThe registration process is inherited from the base \"thing\" template, which means the same fundamental API works for registering miners, PDUs, sensors, and any other device type in the system. What makes each device type unique are the specific connection parameters it requires in the `opts` field.\n\n##### Method Signature\n\n```bash\nhp-rpc-cli -s \u003cRPC_PUBLIC_KEY\u003e -m registerThing -d '{...}'\n```\n\nReplace `\u003cRPC_PUBLIC_KEY\u003e` with the actual hexadecimal public key you obtained from the worker's status file.\n\n##### Parameters\n\nThe `registerThing` method accepts a JSON object with the following structure:\n\n```javascript\n{\n  \"id\": \"optional-custom-id\",        // Optional: Custom identifier for the sensor\n  \"info\": {\n    \"pos\": \"string\",                 // Recommended: Position identifier for the sensor\n    \"meta\": {                        // Optional: Any additional metadata you want to store\n      // Custom fields as needed\n    }\n  },\n  \"opts\": {\n    \"address\": \"string\",             // Required: IP address of the Modbus sensor\n    \"port\": number,                  // Required: Modbus TCP port (typically 502)\n    \"unitId\": number,                // Required: Modbus unit ID (device address)\n    \"register\": number               // Required: Register address to read temperature from\n  },\n  \"tags\": [\"string\"]                 // Optional: Additional tags for filtering and grouping\n}\n```\n\n###### Field Descriptions\n\n**id** (optional string)\nA custom identifier for this sensor. If you don't provide one, the system will automatically generate a UUID. Custom IDs can be useful when you have your own naming scheme or need to reference sensors by meaningful names rather than UUIDs.\n\n**info.pos** (recommended string)\nThe physical position identifier for the sensor. This field is particularly important for SENECA sensors because the alert system uses position naming conventions to determine which temperature thresholds to apply. The position string should follow these patterns:\n\n- Prefix with `lv` for sensors in low-voltage cabinets (e.g., `rack-01_lv-cabinet-1`)\n- Prefix with `tr` for sensors monitoring transformer oil (e.g., `rack-01_tr-transformer-1`)\n\nThe underscore separates the rack location from the specific component. The prefix after the underscore tells the alert system what type of equipment is being monitored, which determines which temperature alerts will be triggered.\n\n**info.meta** (optional object)\nAny additional metadata you want to associate with the sensor. This could include maintenance notes, installation dates, or references to other systems. The structure is completely flexible and won't affect the sensor's operation.\n\n**opts.address** (required string)\nThe IP address where the Modbus sensor can be reached on your network.\n\n**opts.port** (required number)\nThe TCP port for Modbus communication. For standard Modbus TCP, this is typically port 502.\n\n**opts.unitId** (required number)\nThe Modbus unit identifier, also known as the slave address. This tells the Modbus protocol which device to communicate with when multiple devices share the same network connection. Valid values are typically zero through two hundred forty-seven.\n\n**opts.register** (required number)\nThe specific holding register address where the temperature data is stored. For SENECA sensors, this is typically register three, but consult your sensor's documentation to confirm the correct address for your model.\n\n**tags** (optional array of strings)\nAdditional tags for organizing and filtering sensors. The system automatically generates tags based on the sensor type and hierarchy, but you can add your own custom tags here. Tags are used extensively in the query and statistics systems to group related sensors together.\n\n##### Response\n\nUpon successful registration, the method returns the integer `1`. The simplicity of this response reflects the RPC architecture's focus on efficiency. If registration fails for any reason, the method will throw an error with a descriptive message rather than returning a failure status.\n\n**Success Response:**\n```javascript\n1\n```\n\n**Error Responses:**\nInstead of returning error codes, the method throws exceptions. Common errors include:\n\n- `ERR_SLAVE_BLOCK` - Attempted to register a thing on a slave worker (registration only works on master workers)\n- `ERR_THING_TAGS_INVALID` - The tags parameter was provided but is not a valid array\n\n##### Complete Working Examples\n\n###### Example: Registering a Cabinet Temperature Sensor\n\nThis example registers a sensor monitoring the temperature in a low-voltage electrical cabinet. Notice how the position identifier starts with \"lv\" to indicate this is a cabinet sensor.\n\n```bash\nhp-rpc-cli -s a1b2c3d4e5f6... -m registerThing -d '{\n  \"info\": {\n    \"pos\": \"rack-01_lv-cabinet-1\",\n    \"meta\": {\n      \"location\": \"Facility A - Row 3\",\n      \"installation_date\": \"2024-01-15\",\n      \"notes\": \"Main power distribution cabinet\"\n    }\n  },\n  \"opts\": {\n    \"address\": \"192.168.1.100\",\n    \"port\": 502,\n    \"unitId\": 1,\n    \"register\": 3\n  }\n}'\n```\n\nWith this configuration, the alert system will monitor the cabinet temperature and trigger alerts if it exceeds sixty degrees Celsius (high severity) or seventy degrees Celsius (critical severity), based on the default configuration in `config/base.thing.json`.\n\n##### What Happens After Registration\n\nOnce you successfully register a sensor, several things happen automatically:\n\n1. The worker stores the sensor configuration in its embedded database. This ensures the sensor remains registered even if the worker restarts.\n2. The worker immediately attempts to connect to the sensor using the Modbus parameters you provided. If the connection succeeds, it will read an initial temperature value to verify communication is working properly.\n3. The worker adds the sensor to its collection schedule. From this point forward, it will poll the sensor at the interval specified in `collectSnapsItvMs` (which defaults to 60 seconds). Each reading is cached in memory and also stored to the time-series log database for historical analysis.\n4. The alert monitoring system begins evaluating each temperature reading against the configured thresholds. If a reading exceeds a threshold, an alert is created and can be retrieved through the `listThings` method with status information enabled.\n\n##### Troubleshooting Registration Issues\n\nIf your sensor doesn't appear to be working after registration, here are the most common causes:\n\n**Network connectivity:** Verify that the worker can reach the sensor's IP address on your network. Try pinging the address from the machine running the worker.\n\n**Incorrect Modbus parameters:** Double-check that the port, unit ID, and register address match your sensor's configuration. Consult the SENECA sensor documentation or use a Modbus testing tool to verify these values independently.\n\n**Firewall rules:** Ensure that TCP port 502 (or whatever port you specified) is open between the worker and the sensor.\n\n**Unit ID conflicts:** If you have multiple Modbus devices on the same network segment, ensure each has a unique unit ID.\n\nYou can check whether a sensor connected successfully by using the `listThings` method with the status flag enabled, which will show you the last successful reading time and any error messages.\n\n---\n\n## Mock Server\n\nFor development and testing, use the built-in mock server that simulates SENECA sensors.\n\n### Start Mock Server\n\n```bash\nnode mock/server.js --type Seneca -p 5020 -h 0.0.0.0\n```\n\n**Arguments:**\n\n| Argument | Alias | Default | Description |\n|----------|-------|---------|-------------|\n| `--type` | - | - | Sensor type (required: \"Seneca\") |\n| `--port` | `-p` | 5020 | TCP port |\n| `--host` | `-h` | 127.0.0.1 | Bind address |\n| `--error` | - | false | Simulate error conditions |\n| `--mockControlPort` | - | 9999 | Control port for bulk operations |\n\n**Examples:**\n\n```bash\n# Basic mock server\nnode mock/server.js --type Seneca -p 5020\n\n# Mock with errors\nnode mock/server.js --type Seneca -p 5020 --error\n\n# Mock with control agent\nnode mock/server.js --type Seneca -p 5020 --mockControlPort 9999\n\n# Bulk mock instances from file\nnode mock/server.js --bulk ./config/mock-sensors.json --mockControlPort 9999\n```\n\n### Mock Server Features\n\n- **Random Temperature Generation:** Simulates realistic temperature readings (30-40°C)\n- **Error Simulation:** `--error` flag returns 850°C (error condition)\n- **Modbus Protocol:** Responds to READ_HOLDING_REGISTERS (function code 3)\n- **Register Range:** Supports registers 2-5\n- **Control Agent:** Bulk instance management via control port\n\n**Mock Documentation:** [docs/mock.md](./docs/mock.md)\n\n### Test with Mock\n\n```bash\n# Terminal 1: Start mock server\nnode mock/server.js --type Seneca -p 5020 -h 0.0.0.0\n\n# Terminal 2: Start worker\nnode worker.js --wtype wrk-sensor-rack-temp-seneca --env=development --rack rack-0\n\n# Terminal 3: Register mock sensor\nhp-rpc-cli -s wrk -m registerThing -d '{\n  \"info\": {\"pos\": \"test_lv-1\"},\n  \"opts\": {\n    \"address\": \"127.0.0.1\",\n    \"port\": 5020,\n    \"unitId\": 0,\n    \"register\": 3\n  }\n}'\n```\n\n## Alert System\n\nThe worker includes a sophisticated alert system for temperature monitoring.\n\n### Alert Specifications\n\nAlerts are position-aware and apply different thresholds based on sensor location:\n\n#### Cabinet Sensors (position starts with 'lv')\n\n```javascript\n{\n  \"cabinet_temp_high\": {\n    \"params\": { \"temp\": 60 },    // Warning at 60°C\n    \"severity\": \"high\"\n  },\n  \"cabinet_temp_alert\": {\n    \"params\": { \"temp\": 70 },    // Critical at 70°C\n    \"severity\": \"critical\"\n  }\n}\n```\n\n#### Transformer Sensors (position starts with 'tr')\n\n```javascript\n{\n  \"oil_temp_high\": {\n    \"params\": { \"temp\": 80 },    // Warning at 80°C\n    \"severity\": \"high\"\n  },\n  \"oil_temp_critical\": {\n    \"params\": { \"temp\": 90 },   // Critical at 90°C\n    \"severity\": \"critical\"\n  }\n}\n```\n\n### Alert Validation\n\nAlerts are only triggered when:\n1. Snapshot is valid (not null/undefined)\n2. Sensor is online (not timed out)\n3. Configuration exists for alert type\n4. Position matches alert requirements\n5. Temperature is below error threshold (\u003c 850°C. Above that can be assumed to be sensor malfunction)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftetherto%2Fminingos-wrk-sensor-temp-seneca","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftetherto%2Fminingos-wrk-sensor-temp-seneca","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftetherto%2Fminingos-wrk-sensor-temp-seneca/lists"}