Skip to content

Commit 7c7c846

Browse files
committed
bump to v0.2.0 with NBN domain, livebook, and diffo 0.2.0
- version bumped to 0.2.0 to align with new NBN domain - updated to diffo 0.2.0 from hex - new NBN domain livebook (diffo_example.livemd) with Livebook badge in README - changelog updated with v0.2.0 entry
1 parent 3457056 commit 7c7c846

5 files changed

Lines changed: 278 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,14 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
2929
## [v0.0.4](https://github.com/diffo-dev/diffo/compare/v0.0.3..v0.0.4) (2026-03-19)
3030

3131
### Fixes:
32-
* fixed relationship enrichment inconsistent across neo4j versions
32+
* fixed relationship enrichment inconsistent across neo4j versions
33+
34+
## [v0.2.0](https://github.com/diffo-dev/diffo/compare/v0.0.4..v0.2.0) (2026-04-24)
35+
36+
### Maintenance:
37+
* updated to diffo 0.2.0
38+
39+
### Features:
40+
* new NBN domain modelling NBN Ethernet access and constituent resources (UNI, AVC, NTD, CVC, NNI Group, NNI)
41+
* NBN Technology and Speeds as Ash Enum types
42+
* speeds derived from NTD technology and AVC bandwidth_profile via mine action

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ SPDX-License-Identifier: MIT
88

99
[![Module Version](https://img.shields.io/hexpm/v/diffo)](https://hex.pm/packages/diffo_example)
1010
[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen)](https://hexdocs.pm/diffo_example/)
11+
[![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](https://livebook.dev/run?url=https%3A%2F%2Fgithub.com%2Fdiffo-dev%2Fdiffo_example%2Fblob%2Fmain%2Fdiffo_example.livemd)
1112
[![License](https://img.shields.io/hexpm/l/diffo)](https://github.com/diffo-dev/diffo_example/blob/master/LICENSES/MIT.md)
1213
[![REUSE status](https://api.reuse.software/badge/github.com/diffo-dev/diffo_example)](https://api.reuse.software/info/github.com/diffo-dev/diffo_example)
1314

@@ -33,7 +34,9 @@ You need [Neo4j](https://github.com/neo4j/neo4j) available. We recommend the Neo
3334

3435
## Tutorial
3536

36-
Diffo has a livebook and you should use this as an introduction.
37+
Click the **Run in Livebook** badge above to open the interactive tutorial, or find it at [diffo_example.livemd](diffo_example.livemd).
38+
39+
The diffo_example livebook walks through provisioning a complete NBN Ethernet access circuit — NTD, UNI, AVC, CVC, NNI Group, and NNI — showing how the `mine` actions propagate technology, speeds, CVLAN, and port assignments up the resource hierarchy.
3740

3841

3942
## Contributions

diffo_example.livemd

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
<!--
2+
SPDX-FileCopyrightText: 2025 diffo_example contributors <https://github.com/diffo-dev/diffo_example/graphs.contributors>
3+
4+
SPDX-License-Identifier: MIT
5+
-->
6+
7+
# Diffo Example - NBN Domain
8+
9+
```elixir
10+
Mix.install(
11+
[
12+
{:diffo_example, "~> 0.2.0"}
13+
],
14+
consolidate_protocols: false
15+
)
16+
```
17+
18+
## Overview
19+
20+
[Diffo](https://github.com/diffo-dev/diffo) is a Telecommunications Management Forum (TMF) Service and Resource Manager, built for autonomous networks. It is implemented using the [Ash Framework](https://www.ash-hq.org) and stores data in Neo4j via [AshNeo4j](https://github.com/diffo-dev/ash_neo4j).
21+
22+
If you are new to Diffo, start with the [Diffo livebook](https://livebook.dev/run?url=https%3A%2F%2Fgithub.com%2Fdiffo-dev%2Fdiffo%2Fblob%2Fdev%2Fdiffo.livemd) which introduces the core Provider concepts — Specification, Instance, Feature, Characteristic, Party, Place, and Relationship.
23+
24+
Diffo includes a Provider Instance extension that lets you declare specialised TMF Services and Resources using a Spark DSL with very little Elixir code. The [Provider Instance Extension livebook](https://livebook.dev/run?url=https%3A%2F%2Fgithub.com%2Fdiffo-dev%2Fdiffo%2Fblob%2Fdev%2Fdocumentation%2Fhow_to%2Fuse_diffo_provider_instance_extension.livemd) covers this in detail.
25+
26+
The NBN domain in this example was built entirely with that DSL — a declarative model of a realistic NBN Ethernet access hierarchy with minimal custom Elixir, derived from a short domain description. It demonstrates how much can be expressed through the Provider extension alone.
27+
28+
The NBN domain models a fictional NBN Ethernet access circuit and its constituent resources:
29+
30+
* **NbnEthernet** — the parent circuit resource (identified by a PRI)
31+
* **UNI** — User Network Interface at the customer premises
32+
* **AVC** — Access Virtual Circuit (dedicated, carries traffic between UNI and CVC)
33+
* **NTD** — Network Termination Device (installed at customer premises, assigns ports to UNI)
34+
* **CVC** — Connectivity Virtual Circuit (aggregates AVCs, terminates at NNI Group)
35+
* **NNI Group** — group of NNIs at the point of interconnect
36+
* **NNI** — Network-to-Network Interface
37+
38+
## Installing Neo4j and Configuring Bolty
39+
40+
Update the configuration below to match your Neo4j installation and evaluate.
41+
42+
```elixir
43+
config = [
44+
uri: "bolt://localhost:7687",
45+
auth: [username: "neo4j", password: "password"],
46+
user_agent: "diffoExampleLivebook/1",
47+
pool_size: 15,
48+
max_overflow: 3,
49+
prefix: :default,
50+
name: Bolt,
51+
log: false,
52+
log_hex: false
53+
]
54+
```
55+
56+
```elixir
57+
AshNeo4j.BoltyHelper.start(config)
58+
```
59+
60+
```elixir
61+
AshNeo4j.BoltyHelper.is_connected()
62+
```
63+
64+
It is helpful to have a Neo4j browser open locally, typically at http://localhost:7474/browser/
65+
66+
**OPTIONAL** Clear the database before starting:
67+
68+
```elixir
69+
AshNeo4j.Neo4jHelper.delete_all()
70+
```
71+
72+
## Setup Aliases
73+
74+
```elixir
75+
require Ash.Query
76+
alias DiffoExample.Nbn
77+
alias DiffoExample.Nbn.NbnEthernet
78+
alias DiffoExample.Nbn.Uni
79+
alias DiffoExample.Nbn.Avc
80+
alias DiffoExample.Nbn.Ntd
81+
alias DiffoExample.Nbn.Cvc
82+
alias DiffoExample.Nbn.NniGroup
83+
alias DiffoExample.Nbn.Nni
84+
alias DiffoExample.Nbn.Technology
85+
alias DiffoExample.Nbn.Speeds
86+
import Jason, only: [encode: 2]
87+
```
88+
89+
## About NBN
90+
91+
NBN (National Broadband Network) is Australia's wholesale fixed-line access network, operated by NBN Co. It provides standardised access products to Retail Service Providers (RSPs), who in turn deliver internet and other services to end customers.
92+
93+
An RSP typically combines:
94+
95+
* An **NBN Ethernet** access circuit (UNI + AVC) at the customer premises — the access and aggregation layer modelled in this domain
96+
* A **home gateway** device installed at the UNI, which provides the customer's LAN, Wi-Fi, and sometimes voice
97+
* Transport, aggregation, and edge infrastructure connecting the NNI to the RSP's network and on to the internet
98+
99+
NBN Co connects the customer premises to the RSP's network via a Point of Interconnect (POI). The NNI sits at the POI, grouped into NNI Groups. AVCs carrying customer traffic are aggregated onto a CVC, which terminates at the NNI Group. The RSP purchases CVC capacity to carry the aggregate traffic of its customers at that POI.
100+
101+
NBN is delivered over several access technologies — FTTP, FTTN, FTTB, FTTC, HFC, Fixed Wireless, and Satellite — which determine which bandwidth profiles and speeds are available to a given premises.
102+
103+
## Technology and Speeds
104+
105+
The NBN domain defines Technology as an Ash Enum covering all NBN access types:
106+
107+
```elixir
108+
Technology.values()
109+
```
110+
111+
Speeds are derived from a bandwidth_profile and technology combination. For example:
112+
113+
```elixir
114+
Speeds.speeds(:home_fast, :FTTP)
115+
```
116+
117+
```elixir
118+
Speeds.speeds(:home_hyperfast, :HFC)
119+
```
120+
121+
```elixir
122+
Speeds.speeds(:wireless_superfast, :FixedWireless)
123+
```
124+
125+
```elixir
126+
# returns :error for invalid combinations
127+
Speeds.speeds(:home_fast, :FixedWireless)
128+
```
129+
130+
## Building the Network Hinterland
131+
132+
Before we can provision an NBN Ethernet access we need the shared network resources: NNI, NNI Group, and CVC.
133+
134+
Build an NNI — the physical interconnect between the RSP and NBN Co:
135+
136+
```elixir
137+
nni = Nbn.build_nni!(%{})
138+
nni |> Jason.encode!(pretty: true) |> IO.puts
139+
```
140+
141+
Build an NNI Group — a logical grouping of NNIs at a point of interconnect:
142+
143+
```elixir
144+
nni_group = Nbn.build_nni_group!(%{})
145+
nni_group |> Jason.encode!(pretty: true) |> IO.puts
146+
```
147+
148+
Define the NNI Group with an SVLAN assignment and relate the NNI:
149+
150+
```elixir
151+
nni_group = Nbn.define_nni_group!(%{
152+
characteristic_value_updates: [nni_group: [svlan: 100]]
153+
})
154+
nni_group = Nbn.relate_nni_group!(nni_group, %{
155+
relationships: [%{alias: :nni, target_id: nni.id, type: :isAssigned}]
156+
})
157+
nni_group |> Jason.encode!(pretty: true) |> IO.puts
158+
```
159+
160+
Build a CVC — the aggregation virtual circuit that terminates at the NNI Group:
161+
162+
```elixir
163+
cvc = Nbn.build_cvc!(%{})
164+
cvc = Nbn.relate_cvc!(cvc, %{
165+
relationships: [%{alias: :nni_group, target_id: nni_group.id, type: :isAssigned}]
166+
})
167+
cvc |> Jason.encode!(pretty: true) |> IO.puts
168+
```
169+
170+
## Provisioning an NBN Ethernet Access
171+
172+
With the hinterland in place we can provision a customer-facing NBN Ethernet access.
173+
174+
Build an NTD — the device installed at the customer premises:
175+
176+
```elixir
177+
ntd = Nbn.build_ntd!(%{})
178+
ntd = Nbn.define_ntd!(ntd, %{
179+
characteristic_value_updates: [ntd: [technology: :FTTP, ports: [1, 2, 3, 4]]]
180+
})
181+
ntd |> Jason.encode!(pretty: true) |> IO.puts
182+
```
183+
184+
Build a UNI — the interface at the customer premises — and assign a port from the NTD:
185+
186+
```elixir
187+
uni = Nbn.build_uni!(%{})
188+
alias Diffo.Provider.Assignment
189+
ntd = Nbn.assign_port!(ntd, %{
190+
assignment: %Assignment{assignee_id: uni.id, value: 1}
191+
})
192+
ntd |> Jason.encode!(pretty: true) |> IO.puts
193+
```
194+
195+
Relate the UNI back to the NTD so it can mine technology and port from it:
196+
197+
```elixir
198+
uni = Nbn.relate_uni!(uni, %{
199+
relationships: [%{alias: :ntd, target_id: ntd.id, type: :isAssigned}]
200+
})
201+
uni = Nbn.mine_uni!(uni, %{})
202+
uni |> Jason.encode!(pretty: true) |> IO.puts
203+
```
204+
205+
Build an AVC and assign it a CVLAN from the CVC:
206+
207+
```elixir
208+
avc = Nbn.build_avc!(%{})
209+
avc = Nbn.define_avc!(avc, %{
210+
characteristic_value_updates: [avc: [bandwidth_profile: :home_ultrafast]]
211+
})
212+
cvc = Nbn.assign_cvlan!(cvc, %{
213+
assignment: %Assignment{assignee_id: avc.id, value: 200}
214+
})
215+
avc = Nbn.mine_avc!(avc, %{})
216+
avc |> Jason.encode!(pretty: true) |> IO.puts
217+
```
218+
219+
Now build the top-level NBN Ethernet access and relate it to both the UNI and AVC:
220+
221+
```elixir
222+
pri = Nbn.build_nbn_ethernet!(%{})
223+
pri = Nbn.relate_nbn_ethernet!(pri, %{
224+
relationships: [
225+
%{alias: :uni, target_id: uni.id, type: :isAssigned},
226+
%{alias: :avc, target_id: avc.id, type: :isAssigned}
227+
]
228+
})
229+
pri = Nbn.mine_nbn_ethernet!(pri, %{})
230+
pri |> Jason.encode!(pretty: true) |> IO.puts
231+
```
232+
233+
The `mine` action on NbnEthernet extracts technology from the UNI and bandwidth_profile from the AVC and derives the speeds automatically.
234+
235+
## Exploring the Graph
236+
237+
You can query all nodes and relationships in Neo4j browser with:
238+
239+
```cypher
240+
MATCH (n1)-[r]->(n2) RETURN r, n1, n2 LIMIT 50
241+
```
242+
243+
Or from Elixir:
244+
245+
```elixir
246+
AshNeo4j.Cypher.run("MATCH (n1)-[r]->(n2) RETURN r, n1, n2 LIMIT 50")
247+
```
248+
249+
## What Next?
250+
251+
You've provisioned a complete NBN Ethernet access — NTD, UNI, AVC, CVC, NNI Group, and NNI — and seen how the `mine` actions propagate technology, speeds, CVLAN and port assignments up the resource hierarchy automatically.
252+
253+
The Access domain in `diffo_example` shows a similar pattern for DSL access services. Explore `lib/access/` for copper-network equivalents (Cable, Card, Path, Shelf).
254+
255+
If you find Diffo useful please visit and star on [GitHub](https://github.com/diffo-dev/diffo/).

mix.exs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ defmodule DiffoExample.MixProject do
66
@moduledoc false
77
use Mix.Project
88

9-
@version "0.0.4"
9+
@version "0.2.0"
1010
@name "DiffoExample"
1111
@description "Examples for Diffo TMF Service and Resource Manager"
1212
@github_url "https://github.com/diffo-dev/diffo-example"
@@ -45,6 +45,7 @@ defmodule DiffoExample.MixProject do
4545
nil -> default_version
4646
"local" -> [path: "../diffo"]
4747
"main" -> [git: "https://github.com/diffo-dev/diffo.git"]
48+
"0.2.0" -> [git: "https://github.com/diffo-dev/diffo.git", tag: "v0.2.0"]
4849
version -> "~> #{version}"
4950
end
5051
end
@@ -58,6 +59,7 @@ defmodule DiffoExample.MixProject do
5859
logo: "logos/diffo.jpg",
5960
extras: [
6061
"README.md": [title: "Guide"],
62+
"diffo_example.livemd": [title: "Livebook Tutorial"],
6163
"LICENSES/MIT.md": [title: "License"]
6264
]
6365
]
@@ -78,8 +80,7 @@ defmodule DiffoExample.MixProject do
7880
# Run "mix help deps" to learn about dependencies.
7981
defp deps do
8082
[
81-
# {:diffo, diffo_version("~> 0.1.6")},
82-
{:diffo, github: "diffo-dev/diffo", branch: "dev"},
83+
{:diffo, diffo_version("~> 0.2.0")},
8384
{:igniter, "~> 0.6", only: [:dev, :test]},
8485
{:ex_doc, "~> 0.37", only: [:dev, :test], runtime: false}
8586
]

0 commit comments

Comments
 (0)