Compare commits

...

1 Commits
main ... v1

Author SHA1 Message Date
FunctionsAPI
6691fd984a Automatic push from FunctionsAPI 2025-07-08 14:33:17 +00:00
5 changed files with 3777 additions and 1 deletions

3562
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

13
Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
edition = "2024"
name = "web"
version = "0.1.0"
[dependencies]
fathom-function = { git = "ssh://git@github.com/fathom-io/pipeline-calculations.git", branch = "main" }
pipeline-application = { git = "ssh://git@github.com/fathom-io/pipeline-calculations.git", branch = "main" }
serde = { version = "1.0.219", features = ["derive"] }
serde-this-or-that = "0.5.0"
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] }
uom = { version = "0.36" }
uuid = { version = "1" }

View File

@ -1,2 +1,84 @@
# ec8715812c3f497bb8fc4c18113be183
# Add soil resistivity report
Soil resistivity reports
Soil resistivity is a critical parameter in the design of CP systems because:
- It affects current distribution from the anode to the pipe.
- Low resistivity soils (e.g., wet clays) are more conductive and easier to protect pipelines
in.
- High resistivity soils (e.g., dry sand, rock) require more power or more anodes to achieve
protection.
Testing soil resistivity (typically via the Wenner 4-pin method) helps determine:
- CP system design and layout
- Anode type, spacing, and depth
- Expected current requirement and life of anodes
## Input
### Arguments
- `org_id`: as string which should be a valid `uuid` for the organization
- `project_id`: the id of the data project where the pipeline data is found
- `pipeline_id`: an `array` of `strings` which should be valid UUIDs for pipelines
- `inspection_date`: a `string` formatted as an ISO date representing the date of the soil resistivity report
- `starting_point`: a `float` representing the log distance of the starting point of the soil type
- `ending_point`: a `float` representing the log distance of the end point of the soil type
- `soil_type`: a `string` the soil type for the current section of the pipeline possible values
- `clay`
- `sand`
- `silt`
- `resistivity`: a `float` representing the recorded value of the soil's electrical resistivity at this point and time
- `soil_temperature`: a `float` representing the recorded value of the soil temperature at this point and time
- `cp_practice`: a `string` the cathode protection for this section of the pipeline.
- `no_cp`: No cathode protection
- `no_cp_adjacent_risk`: No cathode protection with risk of stray current from adjacent structure
- `cp_outside`: Cathode protection outside of NACE regulation
- `cp_on`: Cathode protection inline with NACE instance on regulation
- `cp_off`: Cathode protection inline with NACE instance off regulation
- `coating_repair_schedule`: a `string` coating repair schedule
- `repaired_or_regularly_replaced`: Coating regularly repaired or replaced
- `never_or_rarely_replaced`: Coating never or rarely replaced
- `inspector`: a `string` representing the identifier of the inspector
- `remarks`: a `string` for any additional remarks about the inspection
## Creating the function on the platform
To create this function on the platform using the `cli` set up the port forwarding as shown in README.
Then run the following command to create the function.
```bash
cargo run functions create \
-f functions/soil_resistivity \
-d "Add a soil resistivity report" \
-i org_id=string \
-i project_id=string \
-i pipeline_id=array \
-i inspection_date=string \
-i starting_point=float \
-i ending_point=float \
-i soil_type=string \
-i resistivity=float \
-i soil_temperature=float \
-i cp_practice=string \
-i coating_repair_schedule=string \
-i inspector=string \
-i remarks=string
```
## Testing the function locally
You can run and test the function locally by running
```bash
cargo run
```
Then you can check it work with `curl` as follows
```bash
jq '. | tojson' functions/soil_resistivity/example_input.json | curl -d '@-' localhost:8080
```

29
example_input.json Normal file
View File

@ -0,0 +1,29 @@
{
"coating_repair_schedule": "never_or_rarely_replaced",
"cp_practice": "cp_on",
"ending_point": 100000,
"inspectionDate": "2025-06-10",
"inspection_date": "2025-06-10",
"inspector": "jbell",
"org_id": "2cbfe270-d195-48ad-aed1-24145924635c",
"pipeline_dataProductId": "01966d47-21f0-7073-a17b-2d98eebe3ca8",
"pipeline_id": [
"01966d47-1d4c-7751-a1f1-0617caa3a00d"
],
"pipeline_organizationId": "2cbfe270-d195-48ad-aed1-24145924635c",
"pipeline_resourceClientIds": [
"pipeline:1680b91f3802a656bbd2cefe8"
],
"pipeline_resourceIds": [
"01966d47-1d4c-7751-a1f1-0617caa3a00d"
],
"pipeline_resourceTypeId": 1,
"pipeline_workspaceId": "680b61b0aedd6f9e639d8699",
"project_id": "680b61b0aedd6f9e639d8699",
"remarks": null,
"resistivity": 20000,
"soilType": "sand",
"soil_temperature": 50,
"soil_type": "sand",
"starting_point": 0
}

90
src/main.rs Normal file
View File

@ -0,0 +1,90 @@
use fathom_function::{chrono::NaiveDate, forms::deserialize_date, tracing};
use pipeline_application::{
application::{
Application, CPPractice, CoatingRepairSchedule, SoilResistivityReport, SoilType,
},
serialization::{serialize_degrees_celsius, serialize_meter, serialize_ohm_centimeter},
};
use serde::{Deserialize, Serialize};
use uom::si::f64::{ElectricalResistivity, Length, ThermodynamicTemperature};
use uuid::Uuid;
#[fathom_function::function]
async fn upload_soil_resistivity_report(input: Input) -> Result<Output, String> {
let app = Application::new_from_compile_env(input.org_id, input.project_id).unwrap();
for pipeline_id in input.pipeline_id {
app.upload_soil_resistivity_report(pipeline_id, &input.report)
.await
.map_err(|err| {
tracing::error!(%pipeline_id, ?err, "Error uploading soil resistivity report");
format!("{err:?}")
})?;
}
Ok(Output {
status: "Success".to_owned(),
})
}
#[derive(Debug, Serialize)]
struct Output {
status: String,
}
#[derive(Debug, Deserialize)]
struct Input {
org_id: Uuid,
project_id: String,
pipeline_id: Vec<Uuid>,
#[serde(flatten)]
report: Report,
}
#[derive(Debug, Deserialize)]
struct Report {
/// The log distance of the starting point of this soil type: the absolute distance measured in
/// meters from the launcher.
#[serde(with = "serialize_meter")]
pub starting_point: Length,
/// The log distance of the end point of this soil type: the absolute distance measured in
/// meters from the launcher.
#[serde(with = "serialize_meter")]
pub ending_point: Length,
/// The date of this field inspection.
#[serde(deserialize_with = "deserialize_date")]
pub inspection_date: NaiveDate,
/// The soil type at this location.
pub soil_type: SoilType,
/// The measured electrical resistivity of the soil.
#[serde(with = "serialize_ohm_centimeter")]
pub resistivity: ElectricalResistivity,
/// The measured temperature of the soil at the time of the inspection.
#[serde(with = "serialize_degrees_celsius")]
pub soil_temperature: ThermodynamicTemperature,
/// The cathode protection practice for this section of the pipeline.
pub cp_practice: CPPractice,
/// The coating repair schedule for this section of the pipeline.
pub coating_repair_schedule: CoatingRepairSchedule,
/// The inspector name or identifier.
pub inspector: String,
/// And additional remarks about the inspection.
pub remarks: Option<String>,
}
impl From<&Report> for SoilResistivityReport {
fn from(value: &Report) -> Self {
Self {
starting_point: value.starting_point,
ending_point: value.ending_point,
inspection_date: value.inspection_date.and_time(Default::default()).and_utc(),
soil_type: value.soil_type,
resistivity: value.resistivity,
soil_temperature: value.soil_temperature,
cp_practice: value.cp_practice,
coating_repair_schedule: value.coating_repair_schedule,
inspector: value.inspector.to_owned(),
remarks: value.remarks.to_owned(),
}
}
}