Compare commits

..

19 Commits

Author SHA1 Message Date
858189d6da Update get_all_assets.php vanaf tagcode.app 2025-11-21 03:00:01 +00:00
ec42ebcb25 Update get_all_assets.php vanaf tagcode.app 2025-11-20 12:15:55 +00:00
f4629e5fcc Update get_all_assets.php vanaf extern endpoint 2025-11-17 15:57:29 +00:00
dafe4c5336 Delete datasets/tagcodeapp_product_models.json 2025-11-17 15:57:15 +00:00
5439d5111a Delete datasets/tagcodeapp_assets.json 2025-11-17 15:57:08 +00:00
1e5ef47a4d Delete datasets/get_all_assets.php 2025-11-17 15:57:02 +00:00
2b87c67876 Update get_all_assets.php vanaf extern endpoint 2025-11-17 15:00:01 +00:00
0db90c0e4b Delete data/get_all_assets.php 2025-11-17 14:58:33 +00:00
1e07093101 Update get_all_assets.php vanaf extern endpoint 2025-11-17 14:58:01 +00:00
ce25ee930a Add ammonium and NOx quantity sensors to assetData 2025-11-12 10:47:41 +01:00
a293e0286a Merge pull request 'Add addtional and updated configs' (#12) from dev-Pieter into main
Reviewed-on: #12
2025-11-06 14:01:32 +00:00
012b8a7ff6 Merge pull request 'Merging to latest updates' (#10) from dev-Rene into main
Reviewed-on: #10
2025-11-03 14:24:58 +00:00
d5d078413c Add flowNumber configuration to define effluent flow handling 2025-10-31 14:03:54 +01:00
17662ef7cb Add total suspended solids sensor to assetData 2025-10-31 13:53:35 +01:00
9d8da15d0e Merge pull request 'Register multiple parents during child registration' (#9) from dev-Pieter into main
Reviewed-on: #9
2025-10-31 10:36:28 +00:00
d503cf5dc9 Merge pull request 'Added does measurement exist in measurement' (#8) from dev-Rene into main
Reviewed-on: #8
2025-10-24 19:20:31 +00:00
f653a1e98c Refactor child setup to support multiple parents consistently 2025-10-24 13:37:26 +02:00
3886277616 Fix bug in parent registration code block 2025-09-29 17:13:34 +02:00
83018fabe0 Allow for multiple parents 2025-09-29 16:06:06 +02:00
15 changed files with 104 additions and 1742 deletions

View File

@@ -66,6 +66,33 @@
"units": ["g/m³", "mol/m³"]
}
]
},
{
"name": "Quantity (Ammonium)",
"models": [
{
"name": "VegaAmmoniaSense 10",
"units": ["g/m³", "mol/m³"]
}
]
},
{
"name": "Quantity (NOx)",
"models": [
{
"name": "VegaNOxSense 10",
"units": ["g/m³", "mol/m³"]
}
]
},
{
"name": "Quantity (TSS)",
"models": [
{
"name": "VegaSolidsProbe",
"units": ["g/m³"]
}
]
}
]
}
@@ -83,7 +110,6 @@
{
"id": "hidrostal-pump-001",
"name": "hidrostal-H05K-S03R",
"units": ["l/s"]
},
{

View File

@@ -0,0 +1 @@
Database connection failed: SQLSTATE[28000] [1045] Access denied for user 'pimmoe1q_rdlab'@'localhost' (using password: YES)

File diff suppressed because it is too large Load Diff

View File

@@ -1,229 +0,0 @@
{
"success": true,
"message": "Product modellen succesvol opgehaald.",
"data": [
{
"id": "1",
"name": "Macbook Air 12",
"product_model_subtype_id": "1",
"product_model_description": null,
"vendor_id": "1",
"product_model_status": null,
"vendor_name": "Apple",
"product_subtype_name": "Laptop",
"product_model_meta": []
},
{
"id": "2",
"name": "Macbook Air 13",
"product_model_subtype_id": "1",
"product_model_description": null,
"vendor_id": "1",
"product_model_status": null,
"vendor_name": "Apple",
"product_subtype_name": "Laptop",
"product_model_meta": []
},
{
"id": "3",
"name": "AirMac 1 128 GB White",
"product_model_subtype_id": "2",
"product_model_description": null,
"vendor_id": "1",
"product_model_status": null,
"vendor_name": "Apple",
"product_subtype_name": "Desktop",
"product_model_meta": []
},
{
"id": "4",
"name": "AirMac 2 256 GB Black",
"product_model_subtype_id": "2",
"product_model_description": null,
"vendor_id": "1",
"product_model_status": null,
"vendor_name": "Apple",
"product_subtype_name": "Desktop",
"product_model_meta": []
},
{
"id": "5",
"name": "AirMac 2 256 GB White",
"product_model_subtype_id": "2",
"product_model_description": null,
"vendor_id": "1",
"product_model_status": null,
"vendor_name": "Apple",
"product_subtype_name": "Desktop",
"product_model_meta": []
},
{
"id": "6",
"name": "Vegabar 14",
"product_model_subtype_id": "3",
"product_model_description": "vegabar 14",
"vendor_id": "4",
"product_model_status": "Actief",
"vendor_name": "vega",
"product_subtype_name": "pressure",
"product_model_meta": {
"machineCurve": {
"np": {
"700": {
"x": [
0,
24.59,
49.18,
73.77,
100
],
"y": [
12.962460720759278,
20.65443723573673,
31.029351002816465,
44.58926412111886,
62.87460150792057
]
},
"800": {
"x": [
0,
24.59,
49.18,
73.77,
100
],
"y": [
13.035157335397209,
20.74906989186132,
31.029351002816465,
44.58926412111886,
62.87460150792057
]
},
"900": {
"x": [
0,
24.59,
49.18,
73.77,
100
],
"y": [
13.064663380158798,
20.927197054134297,
31.107126521989933,
44.58926412111886,
62.87460150792057
]
},
"1000": {
"x": [
0,
24.59,
49.18,
73.77,
100
],
"y": [
13.039271391128953,
21.08680188366637,
31.30899920405947,
44.58926412111886,
62.87460150792057
]
},
"1100": {
"x": [
0,
24.59,
49.18,
73.77,
100
],
"y": [
12.940075520572446,
21.220547481589954,
31.51468295656385,
44.621326083982,
62.87460150792057
]
}
},
"nq": {
"700": {
"x": [
0,
24.59,
49.18,
73.77,
100
],
"y": [
119.13938764447377,
150.12178608265387,
178.82698019104356,
202.3699313222398,
227.06382297856618
]
},
"800": {
"x": [
0,
24.59,
49.18,
73.77,
100
],
"y": [
112.59072109293984,
148.15847460389205,
178.82698019104356,
202.3699313222398,
227.06382297856618
]
},
"900": {
"x": [
0,
24.59,
49.18,
73.77,
100
],
"y": [
105.6217241180404,
144.00502117747064,
177.15212647335034,
202.3699313222398,
227.06382297856618
]
}
}
}
}
},
{
"id": "7",
"name": "Vegabar 10",
"product_model_subtype_id": "3",
"product_model_description": null,
"vendor_id": "4",
"product_model_status": "Actief",
"vendor_name": "vega",
"product_subtype_name": "pressure",
"product_model_meta": []
},
{
"id": "8",
"name": "VegaFlow 10",
"product_model_subtype_id": "4",
"product_model_description": null,
"vendor_id": "4",
"product_model_status": "Actief",
"vendor_name": "vega",
"product_subtype_name": "flow",
"product_model_meta": []
}
]
}

View File

@@ -478,30 +478,6 @@
"min": 0,
"description": "Allowable error between inflow and outflow before adjustments are triggered (m3/h)."
}
},
"thresholdLowVolume": {
"default": 10,
"rules": {
"type": "number",
"min": 0,
"description": "Volume threshold (%) below which the station will shut down pumps to prevent dry running."
}
},
"thresholdHighVolume": {
"default": 90,
"rules": {
"type": "number",
"min": 0,
"description": "Volume threshold (%) above which the station will trigger high level alarms."
}
},
"timeThreshholdSeconds": {
"default": 120,
"rules": {
"type": "number",
"min": 0,
"description": "Time threshold (seconds) used in volume-based safety checks."
}
}
},
"alarms": {

View File

@@ -245,6 +245,10 @@
{
"value": "fysicalControl",
"description": "Controlled via physical buttons or switches; ignores external automated commands."
},
{
"value": "maintenance",
"description": "No active control from auto, virtual, or fysical sources."
}
],
"description": "The operational mode of the machine."
@@ -256,13 +260,7 @@
"type": "object",
"schema":{
"auto": {
"default": [
"statuscheck",
"execmovement",
"execsequence",
"emergencystop",
"entermaintenance"
],
"default": ["statusCheck", "execMovement", "execSequence", "emergencyStop"],
"rules": {
"type": "set",
"itemType": "string",
@@ -270,13 +268,7 @@
}
},
"virtualControl": {
"default": [
"statuscheck",
"execmovement",
"execsequence",
"emergencystop",
"exitmaintenance"
],
"default": ["statusCheck", "execMovement", "execSequence", "emergencyStop"],
"rules": {
"type": "set",
"itemType": "string",
@@ -284,21 +276,24 @@
}
},
"fysicalControl": {
"default": [
"statuscheck",
"emergencystop",
"entermaintenance",
"exitmaintenance"
],
"default": ["statusCheck", "emergencyStop"],
"rules": {
"type": "set",
"itemType": "string",
"description": "Actions allowed in fysicalControl mode."
}
},
"maintenance": {
"default": ["statusCheck"],
"rules": {
"type": "set",
"itemType": "string",
"description": "Actions allowed in maintenance mode."
}
}
},
"description": "Information about valid command sources recognized by the machine."
}
},
"allowedSources":{
"default": {},
@@ -391,22 +386,6 @@
"itemType": "string",
"description": "Sequence of states for booting up the machine."
}
},
"entermaintenance":{
"default": ["stopping","coolingdown","idle","maintenance"],
"rules": {
"type": "set",
"itemType": "string",
"description": "Sequence of states if the machine is running to put it in maintenance state"
}
},
"exitmaintenance":{
"default": ["off","idle"],
"rules": {
"type": "set",
"itemType": "string",
"description": "Sequence of states if the machine is running to put it in maintenance state"
}
}
}
},
@@ -433,6 +412,14 @@
],
"description": "The frequency at which calculations are performed."
}
},
"flowNumber": {
"default": 1,
"rules": {
"type": "number",
"nullable": false,
"description": "Defines which effluent flow of the parent node to handle."
}
}
}

View File

@@ -11,8 +11,12 @@ class ChildRegistrationUtils {
this.logger.debug(`Registering child: ${name} (${id}) as ${softwareType} at ${positionVsParent}`);
// Enhanced child setup
child.parent = this.mainClass;
// Enhanced child setup - multiple parents
if (Array.isArray(child.parent)) {
child.parent.push(this.mainClass);
} else {
child.parent = [this.mainClass];
}
child.positionVsParent = positionVsParent;
// Enhanced measurement container with rich context

View File

@@ -180,6 +180,7 @@ async apiCall(node) {
// Only add tagCode to URL if it exists
if (tagCode) {
apiUrl += `&asset_tag_number=${tagCode}`;
console.log('hello there');
}
assetregisterAPI += apiUrl;
@@ -460,6 +461,10 @@ populateModels(
// Store only the metadata for the selected model
node["modelMetadata"] = modelData.find((model) => model.name === selectedModel);
});
/*
console.log('hello here I am:');
console.log(node["modelMetadata"]);
*/
});
})

View File

@@ -180,6 +180,7 @@ async apiCall(node) {
// Only add tagCode to URL if it exists
if (tagCode) {
apiUrl += `&asset_tag_number=${tagCode}`;
console.log('hello there');
}
assetregisterAPI += apiUrl;
@@ -460,7 +461,10 @@ populateModels(
// Store only the metadata for the selected model
node["modelMetadata"] = modelData.find((model) => model.name === selectedModel);
});
/*
console.log('hello here I am:');
console.log(node["modelMetadata"]);
*/
});
})

View File

@@ -64,7 +64,7 @@ class OutputUtils {
influxDBFormat(changedFields, config , flatTags) {
// Create the measurement and topic using softwareType and name config.functionality.softwareType + .
const measurement = `${config.functionality?.softwareType}_${config.general?.id}`;
const measurement = config.general.name;
const payload = {
measurement: measurement,
fields: changedFields,
@@ -104,23 +104,24 @@ class OutputUtils {
return {
// general properties
id: config.general?.id,
name: config.general?.name,
unit: config.general?.unit,
// functionality properties
softwareType: config.functionality?.softwareType,
role: config.functionality?.role,
// asset properties (exclude machineCurve)
uuid: config.asset?.uuid,
tagcode: config.asset?.tagcode,
geoLocation: config.asset?.geoLocation,
category: config.asset?.category,
supplier: config.asset?.supplier,
type: config.asset?.type,
subType: config.asset?.subType,
model: config.asset?.model,
unit: config.general?.unit,
};
}
processFormat(changedFields,config) {
// Create the measurement and topic using softwareType and name config.functionality.softwareType + .
const measurement = `${config.functionality?.softwareType}_${config.general?.id}`;
const measurement = config.general.name;
const payload = changedFields;
const topic = measurement;
const msg = { topic: topic, payload: payload };

View File

@@ -113,7 +113,7 @@ class Measurement {
// Create a new measurement that is the difference between two positions
static createDifference(upstreamMeasurement, downstreamMeasurement) {
console.log('hello:');
if (upstreamMeasurement.type !== downstreamMeasurement.type ||
upstreamMeasurement.variant !== downstreamMeasurement.variant) {
throw new Error('Cannot calculate difference between different measurement types or variants');

View File

@@ -52,10 +52,6 @@ class state{
return this.stateManager.getRunTimeHours();
}
getMaintenanceTimeHours(){
return this.stateManager.getMaintenanceTimeHours();
}
async moveTo(targetPosition) {

View File

@@ -205,10 +205,6 @@
{
"value": "off",
"description": "Machine is off."
},
{
"value": "maintenance",
"description": "Machine locked for inspection or repair; automatic control disabled."
}
],
"description": "Current state of the machine."
@@ -220,7 +216,7 @@
"type": "object",
"schema": {
"idle": {
"default": ["starting", "off","emergencystop","maintenance"],
"default": ["starting", "off","emergencystop"],
"rules":{
"type": "set",
"itemType": "string",
@@ -284,7 +280,7 @@
}
},
"off": {
"default": ["idle","emergencystop","maintenance"],
"default": ["idle","emergencystop"],
"rules":{
"type": "set",
"itemType": "string",
@@ -292,20 +288,12 @@
}
},
"emergencystop": {
"default": ["idle","off","maintenance"],
"default": ["idle","off"],
"rules":{
"type": "set",
"itemType": "string",
"description": "Allowed transitions from emergency stop state."
}
},
"maintenance": {
"default": ["maintenance","idle","off"],
"rules":{
"type": "set",
"itemType": "string",
"description": "Allowed transitions for maintenance mode"
}
}
},
"description": "Allowed transitions between states."

View File

@@ -48,14 +48,10 @@ class stateManager {
// Define valid transitions (can be extended dynamically if needed)
this.validTransitions = config.state.allowedTransitions;
//runtime tracking
// NEW: Initialize runtime tracking
this.runTimeHours = 0; // cumulative runtime in hours
this.runTimeStart = null; // timestamp when active state began
//maintenance tracking
this.maintenanceTimeStart = null; //timestamp when active state began
this.maintenanceTimeHours = 0; //cumulative
// Define active states (runtime counts only in these states)
this.activeStates = config.state.activeStates;
}
@@ -77,9 +73,8 @@ class stateManager {
); //go back early and reject promise
}
//Time tracking based on active states
// NEW: Handle runtime tracking based on active states
this.handleRuntimeTracking(newState);
this.handleMaintenancetimeTracking(newState);
const transitionDuration = this.transitionTimes[this.currentState] || 0; // Default to 0 if no transition time
this.logger.debug(
@@ -105,7 +100,7 @@ class stateManager {
}
handleRuntimeTracking(newState) {
//Handle runtime tracking based on active states
// NEW: Handle runtime tracking based on active states
const wasActive = this.activeStates.has(this.currentState);
const willBeActive = this.activeStates.has(newState);
if (wasActive && !willBeActive && this.runTimeStart) {
@@ -125,28 +120,6 @@ class stateManager {
}
}
handleMaintenancetimeTracking(newState) {
//is this maintenance time ?
const wasActive = (this.currentState == "maintenance"? true:false);
const willBeActive = ( newState == "maintenance" ? true:false );
if (wasActive && this.maintenanceTimeStart) {
// stop runtime timer and accumulate elapsed time
const elapsed = (Date.now() - this.maintenanceTimeStart) / 3600000; // hours
this.maintenanceTimeHours += elapsed;
this.maintenanceTimeStart = null;
this.logger.debug(
`Maintenance timer stopped; elapsed=${elapsed.toFixed(
3
)}h, total=${this.maintenanceTimeHours.toFixed(3)}h.`
);
} else if (willBeActive && !this.runTimeStart) {
// starting new runtime
this.maintenanceTimeStart = Date.now();
this.logger.debug("Runtime timer started.");
}
}
isValidTransition(newState) {
this.logger.debug(
`Check 1 Transition valid ? From ${
@@ -177,6 +150,7 @@ class stateManager {
return this.descriptions[state] || "No description available.";
}
// NEW: Getter to retrieve current cumulative runtime (active time) in hours.
getRunTimeHours() {
// If currently active add the ongoing duration.
let currentElapsed = 0;
@@ -185,15 +159,6 @@ class stateManager {
}
return this.runTimeHours + currentElapsed;
}
getMaintenanceTimeHours() {
// If currently active add the ongoing duration.
let currentElapsed = 0;
if (this.maintenanceTimeStart) {
currentElapsed = (Date.now() - this.maintenanceTimeStart) / 3600000;
}
return this.maintenanceTimeHours + currentElapsed;
}
}
module.exports = stateManager;