Totogi is a multi-tenant, serverless BSS enhancement platform for communications service providers, also known as telcos or CSPs. CSPs can use Totogi Charging-as-a-Service to collect billing data and usage information from their subscribers using their core networks.
Follow our step-by-step guide for building a basic mobile phone emulator demo app that generates 5G 3GPP charging requests to Totogi Charging-as-a-Service, using APIs to incorporate the charger into existing BSS applications, including:
– Totogi Account Management GraphQL APIs that interact with subscriber accounts and devices
– 5G HTTP Charging APIs that create account charges
– Totogi Notifications documentation for creating real-time account balance notifications
– a Totogi Plan Design GUI that creates plans.
Let’s take a look at how we built the frontend and backend of our charging emulator demo app, and how it integrates with Totogi Charging-as-a-Service:
To build this demo app, we’ll be abstracting away the components of the typical telco/CSP infrastructure, such as actual subscribers and user equipment, the core network components eNodeBs, packet gateways, IP multimedia systems, and few dozen other components not pictured below, depending on the implementation and generation of the CSP core network.
In this example, we are simulating the charging messages that would be generated by the 4G Packet Gateway and 5G Service Management Function. Also, in lieu of operating a core network and order management system, we’ll be creating a frontend application that interacts directly with Totogi Account Management APIs to configure the correct Totogi demo account, create, manage demo accounts and devices, and mock the usage of services like SMS, voice, and data:
While the frontend can use most Totogi APIs (all of the GraphQL APIs that are designed to be consumed from web interfaces), we do need one backend component to proxy the mocked charging requests.
This is because Totogi Charging-as-a-Service is designed to be used as a machine-to-machine API, and to receive information from the local CSP infrastructure like a packet gateway. In fact, the charger actually supports multiple methods of receiving network traffic: both a 4G Diameter interface and a 5G N40 API. In this example, we’ll be using the 5G REST HTTP/2 N40 API.
Build the frontend of the charging emulator demo app
The Totogi charging emulator demo app will have a frontend that emulates a subscriber using their mobile phone. The emulator makes it simple to simulate different types of usage and to visualize the impact on balances and notifications. This demo app accesses several of the Totogi Account Management APIs to do things like load plan and plan version details, determine initial balances, and create and manage new devices in the system that we want to demo with.
Most of this happens behind the scenes and leaves us with a very simple UI that allows us to simulate the most basic components of a subscriber plan:
Here we show an example of a demo device view:
In this example, we see the current balances for that device at the top. These are updated regularly by polling one of the Totogi Account Management APIs.
On the left side, we have a mocked phone that can simulate these different charging interactions by sending requests to a backend proxy that sends them to the Totogi 5G Charging APIs.
On the right side, we have a running log of all the charging interactions to compare against as well as low-balance notifications from Totogi Notifications. These are automatic notifications that CSPs may subscribe to in order to process events like low-balance notifications, plan expiration, and new subscriptions. The power of this sort of subscription enables automated top-up reminders to lifecycle management processing.
Let’s take a look at this in more detail:
Access to Totogi APIs is limited to authorized OAuth 2.0 tokens to use them. The frontend starts by making a request to the Totogi OAuth endpoint to retrieve tokens to authenticate and authorize the account.
Next, it makes a series of requests to Totogi Account Management APIs to find the most recently published plan, then creates a subscriber account and demo device associated with the latest plan.
After this, it uses the UI shown earlier to send various requests for SMS, voice, and data charging requests to a custom backend API. In a standard implementation, this step would go directly to the Totogi charger from the packet gateway (PGW). Since Totogi Charging-as-a-Service is not designed to be called from web applications (it does not enable CORS), our browser-based application needs to send a request to a proxy API that can emulate a PGW.
That proxy API takes a few parameters from the frontend request including:
- device ID
- type of charging request to make (e.g. sms, voice, data)
- volume associated with the request (5 messages/minutes, 2GB data etc.)
After making the request, the frontend continues to monitor the Totogi Account Management APIs to review the balances for the demo device and update the page accordingly. The frontend of the demo app also polls the backend for recently received low-balance notifications and displays them in the right-hand log window.
Build the backend of the charging emulator demo app
Now, let’s see how we built the backend application for the Totogi charging emulator demo app, and how it interacts with the Totogi Account Management APIs as seen in the above sequence diagram. Our backend application handles several different needs:
- processing and storing notifications from Totogi
- providing an API to get saved notifications for different devices
- proxying 5G charging requests for the frontend
To handle these needs, our application acts as a serverless framework application in AWS that creates AWS resources, such as AWS Lambda functions, API Gateway endpoints, an AWS DynamoDB table, and an integration with an Amazon EventBridge bus that receives Totogi Notifications for processing. This application is in the
backend folder of our demo code. Here’s how it works:
With any Serverless Framework application, the core configuration is inside the
serverless.yml file. For us, this starts with configuring a few basics including a service name, framework version, AWS region, and the runtime language and version to use.
We also specify an environment variable for the DynamoDB table name that will be
notifications-prod depending on the stage we’re deploying to.
After that, we configure Cross-Origin Resource Sharing for our HTTP API so that we can use it from our browser app. We also set up the Identity and Access Management permissions our service should have access to. In this case, only Query and PutItem operations on our DynamoDB table.
After all of this we specify the different Lambda Functions and the events that will be triggering them:
This includes the
proxyCharging API endpoint to create 5G charging requests and the
getNotifications endpoint so that our application can fetch any notifications that were sent in from Totogi and then stored by our
processNotifications function is configured to process all the events going into our EventBridge that are arriving from the
266643203619 account (where Totogi sends in events from). The process of creating an Amazon EventBridge and configuring it to work with Totogi is outside of the scope of this post, but it’s a very quick process for any of our customers.
The last portion of the configuration references a file where we describe our DynamoDB infrastructure along with details to help manage Python dependencies and service packaging:
The DynamoDB table used by the application to store notifications data has a partition key (
pk) and sort key (
sk). We are using the single table design pattern, and our keys are prefixed with the object type stored in each row.
With all this infrastructure configured we can look at some of the application code.
Processing Totogi Notifications
When processing notifications our EventBridge Bus has a Rule configured that sends event payloads to Lambda. Here’s what an example event looks like notifying us that the voice balance for a subscriber account was
normal but is now
… and then checking if the event is a threshold event and handling it accordingly:
To handle the threshold, we determine which kind of threshold it is:
Getting Totogi Notifications
Getting back the relevant notifications for our accounts after we’ve stored them in our backend is even simpler.
We set up some dependencies and our DynamoDB Table resource:
… then we run a query on the table using the query string parameters from the incoming GET request event:
This returns all the relevant notifications we’re looking for and we can display them within the frontend.
The 5G Charging Proxy
The final purpose for our backend application is to proxy requests from the frontend and turn them into 5G charging API requests. This is done on the backend for two reasons:
- 5G requests cannot be made directly from a browser due to CORS restrictions on the 5G API
- 5G API requires HTTP2 and most frontend clients do not currently do not support this without additional configuration (Axios, fetch etc.)
This entire process would usually be handled by a local on-premises application, most likely as a component of the PGW. But because we’re mimicking the network traffic we need our own application to handle this for us.
Our frontend UI offers a few structured options for charging requests: voice, SMS, and data consumption. But the backend translates this simple request into a full 5G charging message. Normally in the process of an ongoing phone conversation in a 5G context we would have a series of charging requests like this:
initrequest reserving an initial balance of minutes
updaterequest reserving any additional minutes and recording any minutes used so far
- Any additional
updaterequests for the duration of the call as it continues using the service over time
terminaterequest that completes the reservation and re-allocates any unused minutes.
But for this demo, we’ll do these all at once and in sequence in order to charge precisely what the demo app would like us to.
If we want to charge 5 minutes of voice we send an
init request reserving 5 minutes, then send an
update request using 5 minutes and reserving no additional time, and a final
terminate request ending the session and neither reserving or using any time. At this point the account balance would be updated.
Here’s what this looks like in practice. We create the data for the
terminate requests in a very similar way by including the
ratingGroupNumber (corresponding to voice, text, or data in this case). We also have a
unitTypeIdentifier utility function to pick the type of unit we might need when charging voice minutes (
time), SMS or money (
serviceSpecificUnits), data (
totalVolume), or other custom rating groups. And we have some faked
locationReportingChargingInformation information and an auto-generated timestamp:
update_data request data has an incremented sequence number, and records the units used:
… and the
terminate_data request data simply closes things out without using or requesting any additional volume for the request:
The request data in these requests is sent into the Charging API via the Python HTTP client,
httpx client is HTTP2-compatible and makes sending these requests significantly easier than other common libraries like
requests for Python or
Axios for Node.js. Here’s an example with the init request.
First, we import the required libraries and utility functions:
*_data functions are shown above. The
headers contain required token information to secure the request, and the
*_url functions help us create the 3GPP 5G NCHF URLs we need to send requests to: this is because the URL for update and terminate requests must contain the session ID information from the init request.
Then, we create the
httpx client and functions to handle the three HTTP requests:
With all of this set up, we chain it all together when the request comes in:
When this process completes, the charges will be recorded in our account and the balances will be updated when our frontend queries for the account balances. Also, depending on those balances, this request might trigger a low balance notification.
Demo in action
And that’s the core of this project! Let’s take a look at a full demo with this tool. We’ll start by using Totogi Plan Design GUI, then use this charging emulator demo app to try out our new plan! Take a look at our 3-minute explaier video for an overview:
Building our own network
This is a great start at understanding how to build a charging emulator demo app you can build with Totogi APIs, but we aren’t done yet.
Right now, we’re also working on creating an even more end-to-end demo experience. To do this, we are building our own mobile core network based on Magma and the Citizens Broadband Radio Service in the United States.
Essentially, this means that we will be running our own communications service provider within a few meters of a radio antenna in one of our backyards. We will have a lab phone that uses the CBRS band to communicate with a local eNodeB which is tied over the internet backhaul to our Magma Core 5G network. That network is configured to send usage data to Totogi Charging-as-a-Service for that device. And because our charger integrates directly with our plan designers, we’ll be able to alert and act on that charging data.
Get started today
Everything we’ve shown in this post and demo video is just the most basic functionality that our charger supports. We’re getting ready to showcase all the other amazing features of our charging engine. Watch how easy it is to tackle things like:
- multi-level account hierarchies
- DPI charging
- plan overrides for MVNO providers
… and quite a bit more.
Congratulations, you should now have your very own basic mobile phone emulator demo app that generates 5G 3GPP charging requests to Totogi Charging-as-a-Service, using APIs to incorporate the charger into existing BSS applications. We hope you check out more of our how-to guides to learn more about the capabilities of the Totogi BSS enhancement platform, or book a demo with us today.
charging-as-a-service on aws