Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions doc/examples/csv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# CSV Import Examples

This directory contains example CSV files for testing the CSV import functionality in EditDor.

## Files

### `valid.csv`

A valid CSV file with correct data types and Modbus entities. This file should import without warnings.

**Valid Types:**

- `number`
- `string`
- `boolean`

**Valid Modbus Entities:**

- `HoldingRegister`
- `InputRegister`
- `Coil`
- `DiscreteInput`

### `invalid.csv`

A CSV file with intentional validation errors to demonstrate the warning system. When imported, this file will trigger the following warnings:

1. **Row 2, type**: `number123` is invalid (should be `number`, `string`, or `boolean`)
2. **Row 2, modbus:entity**: `holdingregister` is invalid (case-sensitive, should be `HoldingRegister`)
3. **Row 3, modbus:entity**: `InvalidRegister` is not a recognized Modbus entity
4. **Row 4, type**: `invalid_type` is not a valid type
5. **Row 5, modbus:entity**: `coil` is invalid (case-sensitive, should be `Coil`)

## Usage

1. Open EditDor
2. Select "Thing Description" or "Thing Model"
3. Click "Load a CSV File"
4. Select either `valid.csv` or `invalid.csv`
5. Observe the results:
- `valid.csv`: Should load successfully without warnings
- `invalid.csv`: Should display validation warnings but still load the data

## CSV Format

Required columns:

- `name`: Property name (required)
- `type`: Data type (number, string, or boolean)
- `modbus:entity`: Modbus entity type
- `modbus:address`: Modbus address (required)
- `modbus:unitID`: Modbus unit ID
- `modbus:quantity`: Number of registers
- `modbus:zeroBasedAddressing`: Boolean (true/false)
- `modbus:function`: Modbus function code
- `modbus:mostSignificantByte`: Boolean (true/false)
- `modbus:mostSignificantWord`: Boolean (true/false)
- `href`: Property endpoint path

Note: The validation is case-insensitive for Modbus entities, so `coil`, `Coil`, and `COIL` are all treated as equivalent.
6 changes: 6 additions & 0 deletions doc/examples/csv/invalid.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name,type,modbus:entity,modbus:address,modbus:unitID,modbus:quantity,modbus:zeroBasedAddressing,modbus:function,modbus:mostSignificantByte,modbus:mostSignificantWord,href
temp1,number123,holdingregister,40001,1,1,false,03,true,false,/temp
humidity,number,InvalidRegister,40002,1,1,false,04,false,false,/humidity
pressure,invalid_type,HoldingRegister,40003,1,2,true,03,true,true,/pressure
status,string,coil,00001,1,1,false,01,false,false,/status
alarm,boolean,DiscreteInput,10001,1,1,false,02,false,false,/alarm
6 changes: 6 additions & 0 deletions doc/examples/csv/valid.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name,type,modbus:entity,modbus:address,modbus:unitID,modbus:quantity,modbus:zeroBasedAddressing,modbus:function,modbus:mostSignificantByte,modbus:mostSignificantWord,href
temperature,number,HoldingRegister,40001,1,1,false,03,true,false,/temp
humidity,number,InputRegister,40002,1,1,false,04,false,false,/humidity
pressure,number,HoldingRegister,40003,1,2,true,03,true,true,/pressure
status,boolean,Coil,00001,1,1,false,01,false,false,/status
alarm,boolean,DiscreteInput,10001,1,1,false,02,false,false,/alarm
13 changes: 11 additions & 2 deletions src/components/App/CreateTd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,24 @@ const CreateTd: React.FC<CreateTdProps> = ({
throw new Error("CSV file is empty.");
}

const data = parseCsv(csvContent, true);
const { data, warnings } = parseCsv(csvContent, true);

const parsed = mapCsvToProperties(data);
if (!parsed || Object.keys(parsed).length === 0) {
throw new Error("No valid properties found in the CSV file.");
}

setProperties(parsed);
setError({ open: false, message: "" });

// Display warnings if any
if (warnings.length > 0) {
const warningMessage = warnings
.map((w) => `Row ${w.row}, column "${w.column}": ${w.message}`)
.join("\n");
setError({ open: true, message: `Warnings:\n${warningMessage}` });
} else {
setError({ open: false, message: "" });
}
} catch (err) {
setProperties({});
setError({
Expand Down
Loading