FenixServerApi - dgsoftlabs/FenixModbusS7 GitHub Wiki

FenixServer.Api — User Guide

FenixServer.Api works in two ways:

  1. Embedded — hosted inside FenixServer, starts and stops with the server window.
  2. Standalone console — runs independently as FenixServer.Api.exe, no GUI needed.

Standalone Console Mode

Run FenixServer.Api directly from the command line. Ideal for headless servers, Docker, or Windows Service wrappers.

Starting

FenixServer.Api.exe

Loads the last project from the Windows Registry and starts everything automatically.

FenixServer.Api.exe demo.pse

Loads a specific project file.

FenixServer.Api.exe .\projects\line1.pse

Full path to a project file.

What Happens at Startup

  1. Loads the project (from argument, registry, or starts empty).
  2. Configures the web host on the port from the project settings (default 80).
  3. Starts all communication drivers — Modbus, S7, Internal Tags, Scripts.
  4. Prints a banner and status to the console.
  5. Listens for HTTP requests until you press Ctrl+C.

Console Output

Drivers log to the console in real time:

[14:05:32] [INFO] [PLC_Line1] Communication started
[14:05:32] [DRIVER] [PLC_Line1] started: True
[14:05:32] [DRIVER] [Internal Tags] started: True
[14:05:32] [DRIVER] [Scripts] started: True
Server running. Press Ctrl+C to stop.

Console view

Shutdown

  • Ctrl+C — graceful: stops all drivers, shuts down the web host, exits.
  • Closing the console window also triggers a clean shutdown.
  • Driver errors are printed to console but don't crash the server.

Port Configuration

The port comes from the project's WebServer prefix setting. If not set, defaults to 80.


Embedded Mode (via FenixServer)

When FenixServer starts with a project loaded and communication running, the REST API is available automatically. The server window has a 🌐 Browser button that opens the API in your browser.

For the full server app guide, see FenixServer User Guide.


1. Before You Start

  1. FenixServer must be running with a project loaded.
  2. Communication drivers must be started (▶ Start).
  3. Default address: http://localhost:80 (port is set in the project configuration).

2. Quick Test

GET http://localhost:80/health

→ {"status": "healthy"}

GET http://localhost:80/

→ {"app": "FenixServer.Api", "status": "running", "health": "/health"}


3. Reading Data

Get All Tags

GET http://localhost:80/api/tags

Response (real API format):

[
  {
    "tagName": "Temperature",
    "value": 23.5,
    "formattedValue": "23.50",
    "typeData": "Float",
    "areaData": "HoldingRegisters",
    "startData": 1,
    "deviceAdress": 40001,
    "description": "Room temperature"
  }
]

Key fields: tagName, value, formattedValue, typeData, areaData, startData, deviceAdress, description.

Get a Single Tag

GET http://localhost:80/api/tags/Temperature
{
  "tagName": "Temperature",
  "value": 23.5,
  "formattedValue": "23.50",
  "typeData": "Float"
}

Get Connections

GET http://localhost:80/api/connections

Returns the same JSON format as the legacy WebServer — includes connection parameters, name, driver name, blocked/live status.

Get Graph Data

GET http://localhost:80/api/graph

Returns time-series data for charting:

[
  {
    "label": "Temperature",
    "data": [1715846400000, 23.1], [1715846401000, 23.2](/dgsoftlabs/FenixModbusS7/wiki/1715846400000,-23.1],-[1715846401000,-23.2)
  },
  {
    "label": "Humidity",
    "data": [1715846400000, 58.0](/dgsoftlabs/FenixModbusS7/wiki/1715846400000,-58.0)
  }
]

Each data point is [unix_timestamp_ms, value]. Graph data lives in server memory — it resets when the server restarts.

Get Events

GET http://localhost:80/api/events
[
  {
    "Tm": "2026-05-16T10:00:00+00:00",
    "Mess": "Driver started: PLC_Line1",
    "frDateTime": "16.05.2026 10:00"
  }
]

Holds up to 1000 entries — oldest are automatically removed.


4. Writing Data

To set a tag value, use a query parameter (NOT JSON body):

PUT http://localhost:80/api/tags/Pump_Running?value=0

Or via route:

PUT http://localhost:80/api/tags/Pump_Running/0
Tool Command
cURL curl -X PUT "http://localhost:80/api/tags/Pump_Running?value=0"
PowerShell Invoke-RestMethod -Uri "http://localhost:80/api/tags/Pump_Running?value=0" -Method Put

⚠️ Writing changes the actual device. Double-check the tag address and data type first.


5. Configuring the Sampling Rate

Controls how long graph data is kept (default: 100 seconds).

Action Request
Read interval GET /api/server/buffor → {"seconds": 100}
Set interval PUT /api/server/buffor/300 → {"seconds": 300}

6. Complete Endpoint Reference

Modern API (/api/...)

Method Endpoint Notes
GET / Root — app name and health link
GET /health Health check
GET /api/version API version (1.0)
GET /api/tags All tags: tagName, value, formattedValue, typeData, areaData, startData, deviceAdress, description
GET /api/tags/{name} Single tag: tagName, value, formattedValue, typeData
PUT /api/tags/{name}?value=X Set tag value via query string. Also works as /{name}/{value}
GET /api/connections Active connections
GET /api/graph [{label, data: [[ts, val], ...]}]
GET /api/events [{Tm, Mess, frDateTime}] — max 1000
GET /api/server/buffor Read sampling window (seconds)
PUT /api/server/buffor/{seconds} Set sampling window
GET /api/timer/{name} Timer value
GET /api/user/{name} User info
GET /api/machine/{name} Machine info

All endpoints mirror under /api/v1/....

Legacy Endpoints

Pattern: /{obj}/{name}/{param}/{value}. Accept both GET and POST. Return text/plain.

Example What It Does
/Tags/All/All All tags as JSON array
/Tag/Temp/Value Get tag value (plain text)
/Tag/Temp/Value/25.5 Set tag value
/Connections/All/All Connections JSON
/Graph/All/All Graph series JSON
/Events/All/All Events JSON
/Server/Buffor/Get Read probe counter
/Server/Buffor/Set/200 Set probe counter
/Timer/{name}/Value Timer value
/User/{name}/Value User value
/Machine/{name}/Value Machine value

Legacy tag DTO fields: tagName, areaData, startData, deviceAdress, scAdres, value, formattedValue, typeData, description.


7. Code Examples (updated for real API)

Python

import requests

# Read all tags
tags = requests.get("http://localhost:80/api/tags").json()
for t in tags:
    print(f"{t['tagName']}: {t['value']} ({t['typeData']})")

# Write a value (query param)
requests.put("http://localhost:80/api/tags/Pump_Running?value=1")

JavaScript

// Read tags
fetch("http://localhost:80/api/tags")
  .then(r => r.json())
  .then(tags => tags.forEach(t => console.log(t.tagName, t.value)));

// Write value
fetch("http://localhost:80/api/tags/Pump_Running?value=0", { method: "PUT" });

How It Works

The REST API is an ASP.NET Core app embedded in FenixServer — no IIS, no separate process. Key points:

  • CORS fully open (AllowAnyOrigin) — any browser dashboard can call the API.
  • Port configured in the project settings, default 80.
  • Static files from the Http/ project folder are served automatically — drop an index.html for a web dashboard.
  • Authentication — optional Basic Auth, controlled in project settings.
  • Legacy compatibility — old routes preserved byte-for-byte for existing integrations.