FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index All products support xwh_hub - Microservice - aktueller Stand zum Projekt 2030
Posts: 6983
Joined: Fri Oct 07, 2005 07:07 PM
xwh_hub - Microservice - aktueller Stand zum Projekt 2030
Posted: Mon Sep 08, 2025 03:20 PM
xwh_hub – Mein aktueller Stand zum Projekt 2030

Hallo Freunde,

ich arbeite gerade intensiv an einer neuen Lösung. Es hat eine ganze Weile gedauert, alle möglichen Varianten durchzuspielen und schließlich eine Entscheidung zu treffen, wie wir das Projekt 2030 konkret angehen können.

Mein aktuelles Konzept („xwh_hub“):

FW/Harbour Database Server als Backend – gedacht als neuer Standard für DBF-Datenbanken

FiveWin ManageSoftware läuft direkt am Server, die bestehende Logik bleibt erhalten

FiveWin DBU zur weiteren Pflege der DBF-Tabellen

WebSocket als Transportschicht – läuft direkt auf den Sockets des Betriebssystems, es sind also keine zusätzlichen Bibliotheken notwendig. Das macht die Integration noch einfacher und stabiler.

Für mich steht fest: Dieser Weg ist der richtige, und ich hoffe, dass das vielleicht auch für den einen oder anderen von euch spannend sein könnte.

Ich werde dazu – um die Hauptliste nicht zu stören – alles Weitere hier im GERMAN FORUM posten.

Viele Grüße
Otto
xwh_hub – Technische Referenz (aktueller Stand)
Laufzeit & Server

Lokaler HTTP-Server auf 127.0.0.1:9090 (Winsock2, C89, STARTHTTPSERVER).

Blocking-Accept-Loop mit:

kurzer SO_RCVTIMEO (Zombie-Clients),

/heartbeat-Erkennung via MSG_PEEK,

robustem Header/Body-Parsing inkl. Content-Length & \r\n\r\n/\n\n/\r\r,

Payload-Limit → 413 „Payload too large“,

SO_LINGER für Browser (Chrome/Firefox/Safari),

einheitliches JSON-Antwortgerüst via BuildAndSendJsonResponse/BuildJsonResponse.

Status/Version/Time/Hello (GET): /status, /version, /time, /hello.

WebSocket (serverseitige Basis)

Handshake implementiert (handle_websocket_upgrade): Berechnung Sec-WebSocket-Accept (SHA-1 + Base64 über Crypt32).

Aktuell kein Frame-Loop (d. h. noch kein kontinuierlicher WS-Datenaustausch) – Handshake-Baustein ist da.

Logging & Debug

Dateilog http_log.txt mit Zeitstempel + Zeilennummer (loglineEx, HLOG-Macro).

RAW-Request-Logging (deaktivierbar) nach vollständigem Empfang.

Debugging-Hilfen: DebugHash, DebugArray, ValToChar, logging().

Codepage/UTF-8

DEWIN/Windows-1252 aktiv: hb_cdpSelect("DEWIN"), hb_SetTermCP("DEWIN").

C-Helper:

ISVALIDUTF8, SAFEUTF8 (strippt harte Control-Chars),

CP1252TOUTF8 (1252→UTF-8 mit Mapping 0x80–0x9F).

Harbour-Wrapper: mySafeUtf8, xxxmy_AnsiToUtf8, my_AnsiToUtf8 (vereinfachte Filterung).

INI & Setup

INI-Zugriff via GetPrivateProfileStringA ⇒ GETPVPROFSTRING().

setup() lädt ZPlan.ini (Status 1..22) und baut Farbpalette aFarbe:

TXT/BG/PlanText/PDrucker,

NumToHexColor: numerisch → #RRGGBB.

Endpunkte (Router)
GET

/search?name=... → SearchName()
KUNDEN.DBF (Tag KU_NAME, SET SCOPE TO), liefert bis 200 Treffer: [{name, ort, plz}].

/hello → {status:"ok", message:"Hello works"}

/time → aktuelles Datum/Zeit.

/status | /version → {status:"ok", version:"1.0.0", timestamp:"..."}

POST (JSON)

/heartbeat → HANDLEHEARTBEAT()
{success:.T., type:"heartbeat", heartbeatLastModified:<unix>}

/getindexes → HANDLEGETINDEXES()
Öffnet DBF + zugehöriges CDX, liefert Tags: {"indexes":[[tag, key, for, bag], ...]}.

/readdbf → HANDLEREADDBF()
Paging/Scope/Index optional, felderspezifische oder alle Felder, immer "INDEX": RecNo().
Input:

{"databasePath":"X:\\xwhdaten\\DATAWIN\\KUNDEN.DBF","selectedIndex":"TAGNAME","indexTag":"MEYER","start":1,"end":100,"fields":["NAME","ORT"]}


Output:

{"success":true,"records":[{...}], "Struct":[["name","type","len","dec"], ...]}


/readdbfzplan → HANDLEREADDBF_ZPLAN()
Zeitraumschnitt (ANREISE < dEnd & ABREISE >= dStart), Farben serverseitig (aFarbe, f_Opt_fix()), inkl. BUCHUNGSNR.
Input:

{"databasePath":"...\\BELEGUNG.DBF","dateStart":"YYYY-MM-DD","dateEnd":"YYYY-MM-DD"}


Output:

{"success":true,"count":N,"records":[{"INDEX":123,"ZIMMERNR":"302","ANREISE":"YYYYMMDD","ABREISE":"YYYYMMDD","PLANNAME":"...","FIXBUCHUNG":"...","bgHex":"#RRGGBB","fgHex":"#RRGGBB","BUCHUNGSNR":4711}]}


/addrecord → HANDLEADDRECORD()
Insert mit DBRLOCK(), Typkonvertierung (D/N/L/C/M), Rollback bei Fehler.
Input:

{"databasePath":"...","fields":{"NAME":"...","DATUM":"YYYY-MM-DD",...}}


Output:

{"success":true,"recno":<n>}


/updaterecord → HANDLEEDITRECORD()
Schnelles Setzen eines Feldes (einzelne Spalte) für recordId. (Beispielpfad im Code kommentiert)

/updaterecordfields → HANDLEUPDATERECORD()
Atomare Feld-Updates mit Typkonvertierung (D→CToD, N→VAL).
Input:

{"databasePath":"...","recordId":123,"fields":{"NAME":"...","ANREISE":"YYYY-MM-DD"}}


/deleterecord → HANDLEDELETERECORD()
GOTO recordId + DBRLOCK() + DELETE.

/ziplanupdaterecord → HANDLE_ZIPLAN_EDITRECORD()
Konfliktprüfung Zimmerbelegung (Scopes/Index b_abreise, ordScope pro ZIMMERNR),
Datumskonvertierung (YMD→D.M.Y→CToD), Validierung ADR.DBF (Zimmer existent), HTTP-Status im JSON (200/400/404/409/423/500).
Output bei Konflikt:

{"success":false,"httpstatuscode":"409","status":"occupied","message":"...","zi_nr":"...","from":"dd.mm.yyyy","to":"dd.mm.yyyy"}


Output bei Erfolg:

{"success":true,"httpstatuscode":"200","status":"free", ...}


DB-Zugriff & Sperren

SHARED-Öffnen, DBRLOCK()/FLOCK() wo nötig, sauberes DBUNLOCK()/CLOSE.

Fehlerpfade geben konsistente JSON-Fehlermeldungen zurück (Open/Lock/NotFound/Invalid Input).

Zimmerplan-Farblogik

f_Opt_fix(cFixbuchung) mappt "1".."M", "T", "W", "7", "9" → Index 1..22.

aFarbe[idx] liefert serverseitig bgHex/fgHex (und PlanText/PDrucker).

Initialisierung

PrgInit: Century, Epoch, Deleted ON, Exclusive OFF, Date German, rddSetDefault("DBFCDX"), DESCEND.

Quick Examples (für Tests)
POST /readdbf

POST /readdbf HTTP/1.1
Content-Type: application/json

{
"databasePath": "X:\\xwhdaten\\DATAWIN\\KUNDEN.DBF",
"selectedIndex": "KU_NAME",
"indexTag": "MEYER",
"start": 1,
"end": 50,
"fields": ["NAME","ORT","PLZ"]
}


POST /readdbfzplan

POST /readdbfzplan HTTP/1.1
Content-Type: application/json

{
"databasePath": "X:\\xwhdaten\\DATAWIN\\BELEGUNG.DBF",
"dateStart": "2025-09-01",
"dateEnd": "2025-09-30"
}


POST /addrecord

POST /addrecord HTTP/1.1
Content-Type: application/json

{
"databasePath": "X:\\xwhdaten\\DATAWIN\\KUNDEN.DBF",
"fields": {
"NAME": "Muster GmbH",
"ORT": "Sillian",
"PLZ": "9920",
"ANLAGEDAT": "2025-09-08"
}
}

Continue the discussion