mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-01 02:48:14 +00:00
Initial port of PAWS-C
This commit is contained in:
@@ -1,184 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="0.1782736718">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.1782736718" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration buildProperties="" description="" id="0.1782736718" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
|
||||
<folderInfo id="0.1782736718." name="/" resourcePath="">
|
||||
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.1475280735" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
|
||||
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.1475280735.349926031" name=""/>
|
||||
<builder id="org.eclipse.cdt.build.core.settings.default.builder.1481025371" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.1744114255" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.77598736" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.682734013" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.633855209" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1261857088" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.680528758" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.935501517" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="ocmw_24rdjan17.null.2081730398" name="ocmw_24rdjan17"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<scannerConfigBuildInfo instanceId="0.832805871">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="0.1783974533">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="0.1850940622">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="0.2117040597">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="0.1782736718">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="0.1102575359">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
</cproject>
|
||||
@@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>ocmw_new_test</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>?name?</key>
|
||||
<value></value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.append_environment</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
|
||||
<value>all</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.buildArguments</key>
|
||||
<value></value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.buildCommand</key>
|
||||
<value>make</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
|
||||
<value>clean</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.contents</key>
|
||||
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
|
||||
<value>false</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
|
||||
<value>all</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.stopOnError</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
2
software/pawsc/paws/README.md
Normal file
2
software/pawsc/paws/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# PAWSC
|
||||
Protocol to Access White Space Cellular
|
||||
288
software/pawsc/paws/SpectrumDBClient/.gitignore
vendored
Normal file
288
software/pawsc/paws/SpectrumDBClient/.gitignore
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
**/Properties/launchSettings.json
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
21
software/pawsc/paws/SpectrumDBClient/LICENSE
Normal file
21
software/pawsc/paws/SpectrumDBClient/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
14
software/pawsc/paws/SpectrumDBClient/Makefile
Normal file
14
software/pawsc/paws/SpectrumDBClient/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
#
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
make -C libs
|
||||
make -C apps
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
make -C libs clean
|
||||
make -C apps clean
|
||||
29
software/pawsc/paws/SpectrumDBClient/Makefile.common
Normal file
29
software/pawsc/paws/SpectrumDBClient/Makefile.common
Normal file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
#
|
||||
|
||||
TARGET_PLATFORM ?= native
|
||||
|
||||
C_SRC ?= $(wildcard ./*.c)
|
||||
C_OBJ = $(addprefix obj/$(TARGET_PLATFORM)/,$(patsubst %.c,%.o,$(C_SRC)))
|
||||
DEPS = $(patsubst %.o,%.d,$(C_OBJ))
|
||||
|
||||
LIBS_DIR = $(PRJROOT)/libs
|
||||
|
||||
CFLAGS += -D_GNU_SOURCE -g -MMD -msoft-float -std=c99 -Wall -Werror -Wextra
|
||||
|
||||
INC_DIRS = -I$(LIBS_DIR) -I.
|
||||
C_LIBS = -L$(LIBS_DIR)
|
||||
|
||||
# add SDK stuff
|
||||
ifeq ($(TARGET_PLATFORM),fap)
|
||||
SDK_LIBS_DIR = -L/opt/E40_SDK/sysroots/ppce500v2-ipa-linux-gnuspe/usr/lib
|
||||
INC_DIRS += -I/opt/E40_SDK/sysroots/ppce500v2-ipa-linux-gnuspe/usr/include
|
||||
C_LIBS += $(SDK_LIBS_DIR)
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),native test))
|
||||
SDK_LIBS_DIR = -L/opt/E40_SDK/sysroots/x86_64-cpesdk-linux/usr/lib
|
||||
INC_DIRS += -I/opt/E40_SDK/sysroots/x86_64-cpesdk-linux/usr/include
|
||||
C_LIBS += $(SDK_LIBS_DIR)
|
||||
endif
|
||||
84
software/pawsc/paws/SpectrumDBClient/README.md
Normal file
84
software/pawsc/paws/SpectrumDBClient/README.md
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
# Introduction
|
||||
This is a client which provides LTE access, via a small/femto cell, by communicating with a TVWSDB to negotiate a spectrum. There are two main applications which, together, accomplish this : PAWS and SCTP-AGENT.
|
||||
|
||||
## PAWS
|
||||
This is the application which communicates with an Ofcom-certified TVWS database. The user will need to configure details on the various devices for this to be achieved.
|
||||
Referer to RFC 7545 for more details.
|
||||
|
||||
## SCTP-AGENT
|
||||
This is an application which controls access to the MME itself. It is used to control the transfer of data between the local small-cell eNodeB LTE software, and the MME itself.
|
||||
It uses the information from PAWS to determine whether it needs to block the data transfer. However it can also be configured to ignore the PAWS status.
|
||||
The block diagrams below shows the general topologies.
|
||||
|
||||

|
||||
|
||||
# TVWSDB
|
||||
As discussed, PAWS needs to communicate with a TVWSDB. The user will need to register all clients with this, get security tokens etc, and configure this in the SQL databases mentioned below.
|
||||
|
||||
# Build instructions
|
||||
|
||||
## Set environment variable
|
||||
> export PRJROOT="root-dir-containing-apps-and-libs"
|
||||
|
||||
## SCTP-AGENT
|
||||
### Config options
|
||||
There are some build options in apps/sctp-agent/sctp_cfg_options.h. Change these as required.
|
||||
### Set up real "tcps1", or use dummy.
|
||||
+ The SCTP-agent can communicate in either SCTP ot TCP mode, by setting "SocketInfo.mme_connection_type" to "tcp|sctp".
|
||||
+ If you run in SCTP mode, you need to create a soft-link in the apps/sctp-agent directory to point to dummy_tcps1
|
||||
> cd $PRJROOT/apps/sctp-agent
|
||||
> ln -s dummy_tcps1 tcps1
|
||||
+ NOTE that the dummy_tcps1 is purely used to allow the code to compile. It does not provide a TCP-based access
|
||||
+ If you run in TCP mode, you need to use the tcps1 library, and create a softlink in the apps/sctp-agent directory to point to the directory where you have cloned tcps1lib.
|
||||
> cd $PRJROOT/apps/sctp-agent
|
||||
> ln -s <tcps1lib-directory> tcps1
|
||||
|
||||
|
||||
## Compile code
|
||||
> cd $PRJROOT
|
||||
> make TARGET_PLATFORM=native|fap clean
|
||||
> make TARGET_PLATFORM=native|fap
|
||||
|
||||
|
||||
## Databases (PAWS/SCTP)
|
||||
+ Both the PAWS and SCTP agent are configured using an SQL database.
|
||||
+ The schema for each of these can be found on the "sql_db" subdirectory of each of these apps.
|
||||
+ Furthermore "<app>_native" in each of these directories gives a full example.
|
||||
+ To generate different databases, update the "json" files in these directories and run the Makefile with TARGET_PLATFORM="native|fap"
|
||||
+ Note that the databases are not automatically built by a "make" at the top level.
|
||||
|
||||
|
||||
## Databases (FemTo)
|
||||
This whole small cell client assumes that there is also a "femto.db" that can be read.
|
||||
|
||||
|
||||
## Database locations
|
||||
The location where these databases are found in hardcoded. To change, update the following files accordingly :-
|
||||
### PAWS
|
||||
> apps/paws/fap/main.c
|
||||
>apps/paws/native/main.c
|
||||
### SCTP-AGENT
|
||||
> apps/sctp-agent/fap/device_db_info.h
|
||||
> apps/sctp-agent/native/device_db_info.h
|
||||
|
||||
## TARGET_PLATFORM
|
||||
+ You will see above the TARGET_PLATFORM should be set to "native|fap" when running "make". In this case, "native" means x86 linux.
|
||||
+ For "fap" the user would need to setup their environment as required.
|
||||
|
||||
|
||||
## Contributions
|
||||
Contributions in the form of bug reports, feature requests and PRs are always welcome.
|
||||
|
||||
Please follow these steps before submitting a PR:
|
||||
* Create an issue describing the bug or feature request.
|
||||
* Clone the repository and create a topic branch.
|
||||
* Make changes, adding new tests for new functionality.
|
||||
* Submit a PR.
|
||||
|
||||
## License
|
||||
See [LICENSE](LICENSE).
|
||||
|
||||
## Code of Conduct
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
16
software/pawsc/paws/SpectrumDBClient/apps/Makefile
Normal file
16
software/pawsc/paws/SpectrumDBClient/apps/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
#
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
make -C paws
|
||||
make -C sctp-agent
|
||||
make -C paws db
|
||||
make -C sctp-agent db
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
make -C paws clean
|
||||
make -C sctp-agent clean
|
||||
30
software/pawsc/paws/SpectrumDBClient/apps/paws/Makefile
Normal file
30
software/pawsc/paws/SpectrumDBClient/apps/paws/Makefile
Normal file
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
#
|
||||
|
||||
include ${PRJROOT}/Makefile.common
|
||||
|
||||
C_SRC += $(wildcard $(TARGET_PLATFORM)/*.c)
|
||||
|
||||
APP = paws
|
||||
C_LIBS += -l4gclient -lm
|
||||
|
||||
|
||||
## if TARGET_PLATFORM = fap or native or unittest
|
||||
## ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),fap native))
|
||||
C_LIBS += -lsqlite3 -lssl -lcrypto
|
||||
INC_DIRS += -I./paws_db -I./lte_db -I./sctp_agent_db
|
||||
DB_SRC = $(wildcard paws_db/*.c)
|
||||
DB_SRC += $(wildcard lte_db/*.c)
|
||||
DB_SRC += $(wildcard sctp_agent_db/*.c)
|
||||
C_SRC += $(DB_SRC)
|
||||
DEPS = $(patsubst %.o,%.d,$(C_OBJ))
|
||||
##endif
|
||||
|
||||
include ${PRJROOT}/rules.mk
|
||||
|
||||
.PHONY: db
|
||||
db:
|
||||
make -C sql_db db
|
||||
|
||||
75
software/pawsc/paws/SpectrumDBClient/apps/paws/fap/main.c
Normal file
75
software/pawsc/paws/SpectrumDBClient/apps/paws/fap/main.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "paws_globals.h"
|
||||
|
||||
#include "lte_db_info.h"
|
||||
#include "paws_db_info.h"
|
||||
#include "sctp_agent_db_info.h"
|
||||
#include "paws_common.h"
|
||||
#include "paws_combiner_sm.h"
|
||||
|
||||
#include "utils/types.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
paws_combiner_sm_t* comb = NULL;
|
||||
uint32_t sctp_agent_port;
|
||||
uint32_t sctp_agent_status_perdiocity;
|
||||
|
||||
// wait a while for other services to come up
|
||||
sleep(10);
|
||||
|
||||
if (!(set_paws_db_location("/config/paws.db")))
|
||||
fatal_error("Cant set PAWS-DB location");
|
||||
|
||||
if (!(set_sctp_agent_db_location("/config/sctp_agent.db")))
|
||||
fatal_error("Cant set SCTP-AGENT-DB location");
|
||||
|
||||
if (!(set_lte_db_location("/config/femto.db")))
|
||||
fatal_error("Cant set Device-DB location");
|
||||
|
||||
// create the ssl context.
|
||||
if (!(https_init()))
|
||||
fatal_error("Problem in https_init");
|
||||
|
||||
// get the CloudLog settings
|
||||
get_gPawsLoggerSettings();
|
||||
|
||||
// get the DeviceId
|
||||
populate_gDeviceName();
|
||||
|
||||
// loop until the SCTP settings are read correctly
|
||||
while (1)
|
||||
{
|
||||
if ((get_sctp_agent_info(&sctp_agent_port, &sctp_agent_status_perdiocity)))
|
||||
break;
|
||||
sleep(1); // try in a second
|
||||
}
|
||||
|
||||
if (!(comb = paws_combiner_sm_create("combiner", sctp_agent_port, sctp_agent_status_perdiocity)))
|
||||
fatal_error("Cant initialise sytem");
|
||||
|
||||
PUBLIC_FUNC(comb, Run)(comb);
|
||||
|
||||
paws_combiner_sm_free(&comb);
|
||||
|
||||
PawsGlobalsFree();
|
||||
|
||||
// free ssl txt.
|
||||
https_free();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "paws_device_specific.h"
|
||||
|
||||
//#######################################################################################
|
||||
void system_reboot(void)
|
||||
{
|
||||
system("reboot");
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool reboot_device_on_admin_disable(void)
|
||||
{
|
||||
return false; // for the FAP, the PAWS will not reboot the FAP upon setting Admin=False.
|
||||
// Instead, status=0 will be sent to the SCTP-AGENT agent, which will indirectly cause the eNB sw to disable the radio.
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lte_db_info.h"
|
||||
|
||||
#define MAX_LTE_DB_NAME (100)
|
||||
static char g_lte_db[MAX_LTE_DB_NAME] = "\0";
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool set_lte_db_location(char* db)
|
||||
{
|
||||
if (!db)
|
||||
return false;
|
||||
|
||||
int slen = snprintf(g_lte_db, MAX_LTE_DB_NAME, "%s", db);
|
||||
if ((slen <= 0) || (slen >= MAX_LTE_DB_NAME))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
char* get_lte_db_location(void)
|
||||
{
|
||||
return &g_lte_db[0];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef LTE_DB_INFO_H_
|
||||
#define LTE_DB_INFO_H_
|
||||
|
||||
extern bool set_lte_db_location(char* db);
|
||||
|
||||
extern char* get_lte_db_location(void);
|
||||
|
||||
|
||||
#endif // LTE_DB_INFO_H_
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lte_utils.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t band_id;
|
||||
uint32_t Fdl_low_100khz;
|
||||
uint32_t Fdl_high_100khz;
|
||||
uint32_t Ndl_offset;
|
||||
uint32_t Ndl_high_offset;
|
||||
uint32_t Ful_low_100khz;
|
||||
uint32_t Ful_high_100khz;
|
||||
uint32_t Nul_offset;
|
||||
uint32_t Nul_high_offset;
|
||||
uint16_t bw_mhz; // max bandwidth
|
||||
} lte_band_info_t ;
|
||||
|
||||
static lte_band_info_t lte_band_info[] = {
|
||||
{
|
||||
13, // band_id;
|
||||
7460, // Fdl_low_100khz;
|
||||
7560, // Fdl_high_100khz;
|
||||
5180, // Ndl_offset;
|
||||
5279, // Ndl_high_offset;
|
||||
7770, // Ful_low_100khz;
|
||||
7870, // Ful_high_100khz;
|
||||
23180, // Nul_offset;
|
||||
23279, // Nul_high_offset;
|
||||
10 // bw_mhz - max bandwidth
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static lte_band_info_t* get_lte_band_info(uint16_t band_id)
|
||||
{
|
||||
// walk lte_band_info and find band
|
||||
for (uint32_t i = 0; i < (sizeof(lte_band_info) / sizeof(lte_band_info_t)); i++)
|
||||
{
|
||||
lte_band_info_t* b = <e_band_info[i];
|
||||
if (b->band_id == band_id)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool get_lte_band_channel(uint16_t band_id, lte_direction_e dir, uint32_t* start_hz, uint32_t *end_hz, int32_t *spacing_hz)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
lte_band_info_t* band = get_lte_band_info(band_id);
|
||||
if (band)
|
||||
{
|
||||
found = true;
|
||||
*start_hz = (dir == LTE_UL) ? (band->Ful_low_100khz*100000) : (band->Fdl_low_100khz*100000);
|
||||
*end_hz = *start_hz + (band->bw_mhz*1000000);
|
||||
*spacing_hz = (band->Ful_low_100khz * 100000) - (band->Fdl_low_100khz * 100000);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
uint32_t dl_hz_to_earfcn(uint16_t band_id, uint32_t fdl_)
|
||||
{
|
||||
lte_band_info_t* band = NULL;
|
||||
|
||||
uint32_t fdl = fdl_ / 100000; //convert to 100khz
|
||||
|
||||
if ((band = get_lte_band_info(band_id)))
|
||||
{
|
||||
// is it even in range
|
||||
if ((fdl < band->Fdl_low_100khz) || (fdl > band->Fdl_high_100khz))
|
||||
return 0;
|
||||
|
||||
// Fdl = Fdl_low + 0.1(Ndl - Ndl_offset)
|
||||
// so,
|
||||
// Ndl = ((fdl - Fdl_low) * 10) + Ndl_offset
|
||||
//
|
||||
uint32_t ndl = (fdl - band->Fdl_low_100khz) + band->Ndl_offset;
|
||||
return ndl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
uint32_t ul_hz_to_earfcn(uint16_t band_id, uint32_t ful_)
|
||||
{
|
||||
lte_band_info_t* band = NULL;
|
||||
|
||||
uint32_t ful = ful_ / 100000; //convert to 100khz
|
||||
|
||||
if ((band = get_lte_band_info(band_id)))
|
||||
{
|
||||
// is it even in range
|
||||
if ((ful < band->Ful_low_100khz) || (ful > band->Ful_high_100khz))
|
||||
return 0;
|
||||
|
||||
// Ful = Ful_flow + 0.1(Nul - Nul_offset)
|
||||
// so,
|
||||
// Nul = ((ful - Ful_low) * 10) + Nul_offset
|
||||
//
|
||||
uint32_t nul = (ful - band->Ful_low_100khz) + band->Nul_offset;
|
||||
return nul;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
uint32_t dl_earfcn_to_hz(uint16_t band_id, uint32_t Ndl)
|
||||
{
|
||||
lte_band_info_t* band = NULL;
|
||||
|
||||
if ((band = get_lte_band_info(band_id)))
|
||||
{
|
||||
// is it even in range
|
||||
if ((Ndl < band->Ndl_offset) || (Ndl > band->Ndl_high_offset))
|
||||
return 0;
|
||||
|
||||
// Fdl = Fdl_low + 0.1(Ndl - Ndl_offset)
|
||||
uint32_t fdl = band->Fdl_low_100khz + (Ndl - band->Ndl_offset);
|
||||
fdl *= 100000; //convert to hz
|
||||
return fdl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
uint32_t ul_earfcn_to_hz(uint16_t band_id, uint32_t Nul)
|
||||
{
|
||||
lte_band_info_t* band = NULL;
|
||||
|
||||
if ((band = get_lte_band_info(band_id)))
|
||||
{
|
||||
// is it even in range
|
||||
if ((Nul < band->Nul_offset) || (Nul > band->Nul_high_offset))
|
||||
return 0;
|
||||
|
||||
// Ful = Ful_low + 0.1(Nul - Nul_offset)
|
||||
uint32_t ful = (band->Ful_low_100khz + ((Nul - band->Nul_offset)));
|
||||
ful *= 100000; //convert to hz
|
||||
return ful;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
// pmax and ref_sig_power are stored in units of 0.1dB
|
||||
bool validate_lte_cfg(uint16_t band_id, int bandwidth, int ref_sig_power, int earfcndl, int earfcnul, int pmax)
|
||||
{
|
||||
lte_band_info_t* band = NULL;
|
||||
|
||||
if (!(band = get_lte_band_info(band_id)))
|
||||
return false;
|
||||
|
||||
// is Pmax in range
|
||||
if (pmax < (LTE_PMAX_MIN * 10)) // pmax is stored in units of 0.1dB
|
||||
return false;
|
||||
if (pmax > (LTE_PMAX_MAX * 10)) // pmax is stored in units of 0.1dB
|
||||
return false;
|
||||
|
||||
// bandwidth to Mhz
|
||||
uint32_t bw_hz;
|
||||
if (bandwidth == 25)
|
||||
bw_hz = 5000000;
|
||||
else if (bandwidth == 50)
|
||||
bw_hz = 10000000;
|
||||
else if(bandwidth == 100)
|
||||
bw_hz = 20000000;
|
||||
else
|
||||
return false;
|
||||
|
||||
// is DL in range
|
||||
uint32_t fdl = dl_earfcn_to_hz(band_id, earfcndl);
|
||||
if (fdl == 0)
|
||||
return 0;
|
||||
|
||||
if (((fdl - (bw_hz/2)) < (band->Fdl_low_100khz * 100000)) || ((fdl + (bw_hz/2)) > (band->Fdl_high_100khz * 100000)))
|
||||
return 0;
|
||||
|
||||
// is UL in range
|
||||
uint32_t ful = ul_earfcn_to_hz(band_id, earfcnul);
|
||||
if (ful == 0)
|
||||
return 0;
|
||||
if (((ful - (bw_hz/2)) < (band->Ful_low_100khz * 100000)) || ((ful + (bw_hz/2)) > (band->Ful_high_100khz * 100000)))
|
||||
return 0;
|
||||
|
||||
// ref sig power
|
||||
if (ref_sig_power < (-50 * 10)) // ref_sig_power is stored in units of 0.1dB
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef DEVICE_UTILS_H_
|
||||
#define DEVICE_UTILS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils/types.h"
|
||||
|
||||
#define LTE_PMAX_MIN (-30)
|
||||
#define LTE_PMAX_MAX (33)
|
||||
|
||||
extern bool get_lte_band_channel(uint16_t id, lte_direction_e dir, uint32_t *start_hz, uint32_t *end_hz, int32_t *spacing_hz);
|
||||
|
||||
extern uint32_t dl_hz_to_earfcn(uint16_t band_id, uint32_t fdl);
|
||||
extern uint32_t ul_hz_to_earfcn(uint16_t band_id, uint32_t ful);
|
||||
|
||||
extern uint32_t dl_earfcn_to_hz(uint16_t band_id, uint32_t Ndl);
|
||||
extern uint32_t ul_earfcn_to_hz(uint16_t band_id, uint32_t Nul);
|
||||
|
||||
extern bool validate_lte_cfg(uint16_t band_id, int bandwidth, int ref_sig_power, int earfcndl, int earfcnul, int pmax);
|
||||
|
||||
|
||||
#endif // DEVICE_UTILS_H_
|
||||
|
||||
@@ -0,0 +1,690 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "json-parser/json.h"
|
||||
#include "json-parser/json_utils.h"
|
||||
|
||||
#include "lte_db_info.h"
|
||||
#include "lte_utils.h"
|
||||
|
||||
#include "paws_types.h"
|
||||
#include "paws_common.h"
|
||||
#include "paws_globals.h"
|
||||
#include "paws_dal_device_cfg.h"
|
||||
#include "paws_dal_utils.h"
|
||||
#include "paws_device_specific.h"
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
#define MAX_SQL_LEN (200)
|
||||
static char sql_str[MAX_SQL_LEN];
|
||||
static char tmp[200];
|
||||
#define SQL_STRCAT(s) strncat(sql_str, s, MAX_SQL_LEN - strlen(sql_str) - 1);
|
||||
|
||||
|
||||
static int current_adminState = -1; // we don't write adminState=0. To disable we issue command to SCTP-Agent which will cause eNB software to disable the radio.
|
||||
// -1 means not set
|
||||
|
||||
|
||||
static device_cfg_params_t current_device_cfg = { 0 };
|
||||
|
||||
|
||||
#define MAX_RADIATED_POWER_DBM (36)
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_get_device_name(device_name_t device_name)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int rc;
|
||||
|
||||
memset(device_name, 0, sizeof(device_name_t));
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_lte_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get the DeviceId. We use FAPServiceAccessMgmtLTE.HNBName
|
||||
const char *sql = "SELECT HNBName FROM FAPServiceAccessMgmtLTE";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
char* tmp = (char*)sqlite3_column_text(stmt, 0);
|
||||
if (tmp)
|
||||
{
|
||||
snprintf(device_name, sizeof(device_name_t), "%s", tmp);
|
||||
}
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
// release database
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool sql_get_master_cfg(device_cfg_params_t* cfg, bool use_override)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int rc;
|
||||
|
||||
if (!cfg)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
memset(cfg, 0, sizeof(device_cfg_params_t));
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_lte_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
if (current_adminState == -1) // only read AdminState if it hasn't been read previously
|
||||
{
|
||||
// get the Admin State
|
||||
const char *sql = "SELECT AdminState FROM FAPServiceFAPControlLTE";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
current_adminState = sqlite3_column_int(stmt, 0);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
}
|
||||
cfg->admin_state = current_adminState;
|
||||
|
||||
// get x_000295_external_pa_gain
|
||||
const char *sql4 = "SELECT X_000295_ExternalPAGain FROM FAPServiceCellConfigLTERANRF";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql4, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
cfg->x_000295_external_pa_gain = sqlite3_column_int(stmt, 0);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
// get MaxPower - stored in dB as units of dBM, so we'll multiply by 10 and store it as units of 0.1db, as per other fields.
|
||||
const char *sql2 = "SELECT MaxTxPower FROM FAPServiceCapabilities";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql2, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
cfg->capabilities_max_tx_power = sqlite3_column_int(stmt, 0) * 10;
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
// get MinPower - stored in dB as units of 0.1dB, so we'll keep it like that.
|
||||
const char *sql3 = "SELECT X_000295_MinTxPower FROM FAPServiceCapabilitiesLTE";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql3, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
cfg->capabilities_min_tx_power = sqlite3_column_int(stmt, 0);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
if (use_override)
|
||||
{
|
||||
cfg->bandwidth = current_device_cfg.bandwidth;
|
||||
cfg->earfcndl = current_device_cfg.earfcndl;
|
||||
cfg->earfcnul = current_device_cfg.earfcnul;
|
||||
cfg->ref_sig_power = current_device_cfg.ref_sig_power;
|
||||
cfg->pmax = current_device_cfg.pmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get bandwidth, ref_sig_power, earfcndl, earfcnul
|
||||
const char *sql4 = "SELECT ULBandwidth, ReferenceSignalPower, EARFCNDL, EARFCNUL FROM FAPServiceCellConfigLTERANRF";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql4, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
cfg->bandwidth = sqlite3_column_int(stmt, 0);
|
||||
cfg->ref_sig_power = sqlite3_column_int(stmt, 1) * 10;
|
||||
cfg->earfcndl = sqlite3_column_int(stmt, 2);
|
||||
cfg->earfcnul = sqlite3_column_int(stmt, 3);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
// get Pmax
|
||||
const char *sql5 = "SELECT PMax FROM FAPServiceCellConfigLTERANMobilityIdleModeIntraFreq";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql5, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
cfg->pmax = sqlite3_column_int(stmt, 0) * 10;
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
}
|
||||
|
||||
// release database
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
//
|
||||
//
|
||||
// +---------+ +---------+ +------------+
|
||||
// | FAP |------------------------>| LRE |----------*------------>| Antenna |------------*-------------->
|
||||
// +---------+ +---------+ | +------------+ |
|
||||
// | |
|
||||
// | |
|
||||
// total_ref_sig_power total_power
|
||||
// (max_pa_power) (max_tx_power)
|
||||
//
|
||||
// total_power = that specified in the AVAIL_SPEC_RESP (or by Ofcom for Override)
|
||||
// min_pa_power <= total_reg_sig_power <= max_pa_power
|
||||
// total_ref_sig_power + antenna_gain <= max_tx_power
|
||||
//
|
||||
static bool limit_and_validate_cfg(void* logger, device_cfg_params_t* dst, int min_pa_power, int max_pa_power, int master_antenna_gain, int max_tx_power, int lre)
|
||||
{
|
||||
float _10log_numRBelements = 0;
|
||||
|
||||
// total power = 10xlog(num_100k_blocks) + dbm_per100k;
|
||||
// fix the 10xlog(num_100k_blocks) based on bandwdith
|
||||
if (dst->bandwidth == 25)
|
||||
{
|
||||
_10log_numRBelements = 24.77;
|
||||
}
|
||||
else if (dst->bandwidth == 50)
|
||||
{
|
||||
_10log_numRBelements = 27.78;
|
||||
}
|
||||
else if (dst->bandwidth == 100)
|
||||
{
|
||||
_10log_numRBelements = 30.79;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
dst->capabilities_min_tx_power = min_pa_power;
|
||||
dst->capabilities_max_tx_power = max_pa_power;
|
||||
dst->antenna_gain = master_antenna_gain;
|
||||
dst->x_000295_external_pa_gain = lre;
|
||||
dst->total_ref_sig_power = dst->ref_sig_power + (_10log_numRBelements*10) + dst->antenna_gain;
|
||||
|
||||
// check the max radiated power is not exceeded
|
||||
if (dst->total_ref_sig_power > max_tx_power)
|
||||
{
|
||||
char dbg[200];
|
||||
sprintf(dbg, "Limiting DL power to maximum allowed to be radiated [%.2fdBm]", max_tx_power / 10.0);
|
||||
logger_log(logger, dbg, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
dst->total_ref_sig_power = max_tx_power;
|
||||
dst->limited = true;
|
||||
}
|
||||
|
||||
// take off the antenna gain to check the max_pa and min_pa
|
||||
dst->total_ref_sig_power -= dst->antenna_gain;
|
||||
|
||||
// check min
|
||||
if (dst->total_ref_sig_power < min_pa_power)
|
||||
{
|
||||
char dbg[200];
|
||||
sprintf(dbg, "Invalid cfg : Allowed DL power is below Minimum Power of the device. Ref_sig_power=%.2fdBm Minimum_Ref_sig_power=%.2fdBm \n",
|
||||
(float)dst->total_ref_sig_power/10.0, (float)min_pa_power/10.0);
|
||||
logger_log(logger, dbg, LOG_ERROR, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
return false;
|
||||
}
|
||||
// check max
|
||||
if (dst->total_ref_sig_power > max_pa_power)
|
||||
{
|
||||
char dbg[200];
|
||||
sprintf(dbg, "Limiting DL power to maximum of the device [%.2fdBm]", dst->capabilities_max_tx_power/10.0);
|
||||
logger_log(logger, dbg, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
dst->total_ref_sig_power = max_pa_power;
|
||||
dst->limited = true;
|
||||
}
|
||||
|
||||
dst->ref_sig_power = dst->total_ref_sig_power - (_10log_numRBelements * 10);
|
||||
|
||||
|
||||
// check Pmax min
|
||||
if (dst->pmax < (LTE_PMAX_MIN * 10))
|
||||
{
|
||||
char dbg[200];
|
||||
sprintf(dbg, "Invalid cfg : Allowed UL power is below Minimum Power of an LTE UE. PMax=%.2fdBm PMax(min)=%d.0dBm \n",
|
||||
(float)dst->pmax / 10.0, LTE_PMAX_MIN);
|
||||
logger_log(logger, dbg, LOG_ERROR, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check Pmax max
|
||||
if (dst->pmax > (LTE_PMAX_MAX * 10))
|
||||
{
|
||||
char dbg[200];
|
||||
sprintf(dbg, "Limiting UL power to maximum of an LTE UE [%d.0dBm]", LTE_PMAX_MAX);
|
||||
logger_log(logger, dbg, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
dst->pmax = (LTE_PMAX_MAX * 10);
|
||||
dst->limited = true;
|
||||
}
|
||||
|
||||
// fail safe - just to double check the valiues are consistent
|
||||
if (!(validate_lte_cfg(13, dst->bandwidth, dst->ref_sig_power, dst->earfcndl, dst->earfcnul, dst->pmax)))
|
||||
{
|
||||
char dbg[200];
|
||||
sprintf(dbg, "Invalid cfg : Bandwidth=%d(RB) earfcndl=%d earfcnul=%d ref_sig_power=%.2fdBm Pmax=%.2fdBm",
|
||||
dst->bandwidth, dst->earfcndl, dst->earfcnul, (float)dst->ref_sig_power/10.0, (float)dst->pmax/10.0);
|
||||
logger_log(logger, dbg, LOG_ERROR, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool create_device_cfg_params(void* logger, device_cfg_params_t* dst, int min_tx_power, int max_tx_power, device_cfg_t* paws_cfg, int master_antenna_gain, int lre)
|
||||
{
|
||||
float _10log_numRBelements = 0;
|
||||
float _10log_num100kblocks = 0;
|
||||
|
||||
if ((!dst) || (!paws_cfg))
|
||||
return false;
|
||||
|
||||
memset(dst, 0, sizeof(device_cfg_params_t));
|
||||
|
||||
// set the capabilities
|
||||
dst->capabilities_min_tx_power = min_tx_power;
|
||||
dst->capabilities_max_tx_power = max_tx_power;
|
||||
dst->antenna_gain = master_antenna_gain;
|
||||
dst->x_000295_external_pa_gain = lre;
|
||||
|
||||
// adminState
|
||||
dst->admin_state = paws_cfg->device_enabled;
|
||||
|
||||
if (dst->admin_state)
|
||||
{
|
||||
// bandwidth
|
||||
if (paws_cfg->bandwidth == 5000000)
|
||||
dst->bandwidth = 25;
|
||||
else if (paws_cfg->bandwidth == 10000000)
|
||||
dst->bandwidth = 50;
|
||||
else if (paws_cfg->bandwidth == 20000000)
|
||||
dst->bandwidth = 100;
|
||||
else
|
||||
return false;
|
||||
|
||||
// uarcfn
|
||||
if ((dst->earfcndl = dl_hz_to_earfcn(13, paws_cfg->dl_start_hz + (paws_cfg->bandwidth / 2))) == 0)
|
||||
return false;
|
||||
if ((dst->earfcnul = ul_hz_to_earfcn(13, paws_cfg->ul_start_hz + (paws_cfg->bandwidth / 2))) == 0)
|
||||
return false;
|
||||
|
||||
// total power = 10xlog(num_100k_blocks) + dbm_per100k;
|
||||
// fix the 10xlog(num_100k_blocks) based on bandwdith
|
||||
if (dst->bandwidth == 25)
|
||||
{
|
||||
_10log_numRBelements = 24.77;
|
||||
_10log_num100kblocks = 16.98;
|
||||
}
|
||||
else if (dst->bandwidth == 50)
|
||||
{
|
||||
_10log_numRBelements = 27.78;
|
||||
_10log_num100kblocks = 20.00;
|
||||
}
|
||||
else if (dst->bandwidth == 100)
|
||||
{
|
||||
_10log_numRBelements = 30.79;
|
||||
_10log_num100kblocks = 23.01;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
dst->pmax = (int)((_10log_num100kblocks + paws_cfg->ul_dbm_per100k) * 10.0);
|
||||
|
||||
dst->limited = false;
|
||||
|
||||
// Ref power must fall between MinTxPower and MaxTxPower
|
||||
uint32_t max_total_power = (_10log_num100kblocks + paws_cfg->dl_dbm_per100k) * 10;
|
||||
dst->total_ref_sig_power = max_total_power - dst->antenna_gain;
|
||||
// create power per 100k
|
||||
dst->ref_sig_power = dst->total_ref_sig_power - (_10log_numRBelements * 10);
|
||||
|
||||
if (!(limit_and_validate_cfg(logger, dst, dst->capabilities_min_tx_power, dst->capabilities_max_tx_power, master_antenna_gain, max_total_power, lre)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool process_device_cfg_params(void* logger, device_cfg_params_t* new_, device_cfg_params_t* curr, bool* admin_state_changed, bool *cfg_changed, bool *reboot_needed, bool spectrum_override_present)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
char* error_msg = NULL;
|
||||
|
||||
sql_str[0] = '\0';
|
||||
tmp[0] = '\0';
|
||||
|
||||
if ((!new_) || (!curr) || (!cfg_changed) || (!reboot_needed))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
*cfg_changed = false;
|
||||
*reboot_needed = false;
|
||||
*admin_state_changed = false;
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_lte_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// write params
|
||||
if (new_->admin_state)
|
||||
{
|
||||
// ULBandwidth, ReferenceSignalPower, EARFCNDL, EARFCNUL
|
||||
// build SQL command
|
||||
|
||||
sprintf(tmp, "UPDATE FAPServiceCellConfigLTERANRF SET "); SQL_STRCAT(tmp);
|
||||
// Bandwidth
|
||||
if (new_->bandwidth != curr->bandwidth)
|
||||
{
|
||||
sprintf(tmp, "ULBandwidth = %d, DLBandwidth = %d", new_->bandwidth, new_->bandwidth); SQL_STRCAT(tmp);
|
||||
*cfg_changed = true;
|
||||
current_device_cfg.bandwidth = new_->bandwidth;
|
||||
}
|
||||
// ReferenceSignalPower
|
||||
if ((new_->ref_sig_power/10) != (curr->ref_sig_power/10)) // divide by 10 as the femto,db does not have granularity to 0.1db
|
||||
{
|
||||
if (*cfg_changed) SQL_STRCAT(",");
|
||||
sprintf(tmp, "ReferenceSignalPower = %d", new_->ref_sig_power / 10); SQL_STRCAT(tmp);
|
||||
*cfg_changed = true;
|
||||
current_device_cfg.ref_sig_power = new_->ref_sig_power;
|
||||
}
|
||||
|
||||
// EARFCNDL
|
||||
if (new_->earfcndl != curr->earfcndl)
|
||||
{
|
||||
if (*cfg_changed) SQL_STRCAT(",");
|
||||
sprintf(tmp, "EARFCNDL = %d", new_->earfcndl); SQL_STRCAT(tmp);
|
||||
*cfg_changed = true;
|
||||
current_device_cfg.earfcndl = new_->earfcndl;
|
||||
}
|
||||
// EARFCNUL
|
||||
if (new_->earfcnul != curr->earfcnul)
|
||||
{
|
||||
if (*cfg_changed) SQL_STRCAT(",");
|
||||
sprintf(tmp, "EARFCNUL = %d", new_->earfcnul); SQL_STRCAT(tmp);
|
||||
*cfg_changed = true;
|
||||
current_device_cfg.earfcnul = new_->earfcnul;
|
||||
}
|
||||
|
||||
if (*cfg_changed)
|
||||
{
|
||||
logger_log(logger, sql_str, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
if (!spectrum_override_present)
|
||||
{
|
||||
// run command
|
||||
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pmax
|
||||
if ((new_->pmax/10) != (curr->pmax/10)) // divide by 10 as the femto.db does not have granularity to 0.1db
|
||||
{
|
||||
*cfg_changed = true;
|
||||
current_device_cfg.pmax = new_->pmax;
|
||||
// build SQL command
|
||||
sprintf(sql_str, "UPDATE FAPServiceCellConfigLTERANMobilityIdleModeIntraFreq SET Pmax=%d", new_->pmax / 10);
|
||||
logger_log(logger, sql_str, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
if (!spectrum_override_present)
|
||||
{
|
||||
// run command
|
||||
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AdminState
|
||||
if (new_->admin_state != current_adminState)
|
||||
{
|
||||
current_adminState = new_->admin_state;
|
||||
*admin_state_changed = true;
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (sql_hdl)
|
||||
sqlite3_close(sql_hdl);
|
||||
|
||||
if ((*cfg_changed) && (new_->admin_state == true))
|
||||
*reboot_needed = true;
|
||||
|
||||
// per device, check if device should always be rebooted when Admin is set to False)
|
||||
if ((*admin_state_changed) && (new_->admin_state == false) && (reboot_device_on_admin_disable()))
|
||||
{
|
||||
*reboot_needed = true;
|
||||
}
|
||||
|
||||
// log it
|
||||
if (new_->admin_state)
|
||||
{
|
||||
float dl_mhz = (float)dl_earfcn_to_hz(13, new_->earfcndl) / 1000000;
|
||||
float ul_mhz = (float)ul_earfcn_to_hz(13, new_->earfcnul) / 1000000;
|
||||
float ref_sig_pwr = (new_->admin_state) ? ((float)new_->ref_sig_power / 10.0) : -99.9;
|
||||
float total_ref_sig_pwr = (new_->admin_state) ? ((float)new_->total_ref_sig_power / 10.0) : -99.9;
|
||||
float ul_pmax = (new_->admin_state) ? ((float)new_->pmax / 10.0) : -99.9;
|
||||
|
||||
char log_j_str[300];
|
||||
sprintf(log_j_str, "{\"reboot\":%d, \"CfgChanged\":%d, \"device_enabled\":%d, \"Limited\":%d, \"Bandwidth\":%d, \"EARFCNDL\":%d, \"DL_MHz\":%.2f, \"EARFCNUL\":%d, \"UL_MHz\":%.2f, \"RefSigPower\":%.2f, \"TotalRefSigPower\":%.2f, \"Pmax\":%.2f, \"DeviceAntennaGain\":%.2f, \"LRE\":%.2f, \"DeviceMinPower\":%.2f, \"DeviceMaxPower\":%.2f }",
|
||||
*reboot_needed, *cfg_changed, new_->admin_state,
|
||||
new_->limited, new_->bandwidth, new_->earfcndl, dl_mhz, new_->earfcnul, ul_mhz, ref_sig_pwr, total_ref_sig_pwr, ul_pmax,
|
||||
(float)new_->antenna_gain / 10.0, (float)new_->x_000295_external_pa_gain / 10.0, (float)new_->capabilities_min_tx_power / 10.0, (float)new_->capabilities_max_tx_power / 10.0);
|
||||
logger_log(logger, log_j_str, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
// DeviceCfg Cloud log
|
||||
if (gPawsCloudLogger)
|
||||
{
|
||||
cloud_logger_log(gPawsCloudLogger, "Device-Cfg", gDeviceName, CLOUD_LOGGER_DEVICE_CFG, PAWS_LOG_TYPE, log_j_str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char log_j_str[300];
|
||||
sprintf(log_j_str, "{\"reboot\":%d, \"CfgChanged\":%d, \"device_enabled\":%d, \"RefSigPower\":-99.9, \"TotalRefSigPower\":-99.9, \"Pmax\":-99.9, \"DeviceAntennaGain\":%.2f, \"LRE\":%.2f, \"DeviceMinPower\":%.2f, \"DeviceMaxPower\":%.2f }",
|
||||
*reboot_needed, *cfg_changed, new_->admin_state,
|
||||
(float)new_->antenna_gain / 10.0, (float)new_->x_000295_external_pa_gain / 10.0, (float)new_->capabilities_min_tx_power / 10.0, (float)new_->capabilities_max_tx_power / 10.0);
|
||||
logger_log(logger, log_j_str, LOG_NOTICE, "Device-Cfg", true, true, NULL, 0, NULL, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
// DeviceCfg Cloud log
|
||||
if (gPawsCloudLogger)
|
||||
{
|
||||
cloud_logger_log(gPawsCloudLogger, "Device-Cfg", gDeviceName, CLOUD_LOGGER_DEVICE_CFG, PAWS_LOG_TYPE, log_j_str);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
*cfg_changed = false;
|
||||
*reboot_needed = false;
|
||||
*admin_state_changed = false;
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_config_master_device(void* logger, device_cfg_t* paws_cfg, bool* admin_state_changed, bool* cfg_changed, bool* reboot_needed, paws_setting_override_t* spectrum_override, paws_antenna_info_t* antenna_info)
|
||||
{
|
||||
device_cfg_params_t curr_device_cfg;
|
||||
device_cfg_params_t new_device_cfg;
|
||||
|
||||
if (!(sql_get_master_cfg(&curr_device_cfg, spectrum_override->present)))
|
||||
return false;
|
||||
|
||||
// create new config
|
||||
if (!(create_device_cfg_params(logger, &new_device_cfg, curr_device_cfg.capabilities_min_tx_power, curr_device_cfg.capabilities_max_tx_power, paws_cfg, antenna_info->gain, curr_device_cfg.x_000295_external_pa_gain)))
|
||||
{
|
||||
// force the FAP to be disabled
|
||||
new_device_cfg.admin_state = 0;
|
||||
}
|
||||
|
||||
// write the config if necessary
|
||||
if (!(process_device_cfg_params(logger, &new_device_cfg, &curr_device_cfg, admin_state_changed, cfg_changed, reboot_needed, spectrum_override->present)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void paws_reboot_master_device(void)
|
||||
{
|
||||
system_reboot();
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_config_master_device_override(void* logger, paws_setting_override_t* spectrum_override, paws_antenna_info_t* antenna_info)
|
||||
{
|
||||
device_cfg_params_t curr_device_cfg;
|
||||
device_cfg_params_t new_device_cfg;
|
||||
memset(&curr_device_cfg, 0, sizeof(device_cfg_params_t));
|
||||
memset(&new_device_cfg, 0, sizeof(device_cfg_params_t));
|
||||
|
||||
bool admin_state_changed, cfg_changed, reboot_needed;
|
||||
UNUSED_PARAM(antenna_info);
|
||||
|
||||
if (spectrum_override->present)
|
||||
{
|
||||
if (!(sql_get_master_cfg(&curr_device_cfg, false)))
|
||||
return false;
|
||||
|
||||
// create new config
|
||||
new_device_cfg.admin_state = true;
|
||||
new_device_cfg.bandwidth = spectrum_override->bandwidth_rb;
|
||||
new_device_cfg.earfcndl = spectrum_override->earfcndl;
|
||||
new_device_cfg.earfcnul = spectrum_override->earfcnul;
|
||||
new_device_cfg.ref_sig_power = spectrum_override->ref_sig_pwr;
|
||||
new_device_cfg.pmax = spectrum_override->pmax;
|
||||
if (!(limit_and_validate_cfg(logger, &new_device_cfg, curr_device_cfg.capabilities_min_tx_power, curr_device_cfg.capabilities_max_tx_power, antenna_info->gain, (MAX_RADIATED_POWER_DBM * 10), curr_device_cfg.x_000295_external_pa_gain)))
|
||||
{
|
||||
// force the FAP to be disabled
|
||||
new_device_cfg.admin_state = 0;
|
||||
}
|
||||
|
||||
// write the config if necessary
|
||||
if (!(process_device_cfg_params(logger, &new_device_cfg, &curr_device_cfg, &admin_state_changed, &cfg_changed, &reboot_needed, false)))
|
||||
return false;
|
||||
|
||||
if (reboot_needed)
|
||||
{
|
||||
paws_reboot_master_device();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DAL_CFG_DEVICE_H_
|
||||
#define PAWS_DAL_CFG_DEVICE_H_
|
||||
|
||||
#include "paws_types.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// NOTE: all power fields are stored in this structure in units of 0.1dB.
|
||||
// Some are written to the SQL db in this form, and some are converted to dB. This is governed by the SQL schema on a per fields basis.
|
||||
|
||||
bool admin_state; // enabled/disabled [FAPServiceFAPControlLTE].[AdminState]
|
||||
int x_000295_external_pa_gain; // [-500:+500] in 0.1dBm, SQL: 0.1db [FAPServiceCellConfigLTERANRF].[X_000295_ExternalPAGain]
|
||||
int capabilities_max_tx_power; // converted from dbM to units of 0.1dBm SQL: db [FAPServiceCapabilities].[MaxTxPower]
|
||||
int capabilities_min_tx_power; // [-500:+500] in 0.1dBm, SQL: 0.1db [FAPServiceCapabilitiesLTE].[X_000295_MinTxPower]
|
||||
int bandwidth; // in Number-of-RB 5MHz=25, 10MHz=50, 20MHz=100 [FAPServiceCellConfigLTERANRF].[ULBandwidth]
|
||||
int earfcndl; // [FAPServiceCellConfigLTERANRF].EARFCNDL
|
||||
int earfcnul; // [FAPServiceCellConfigLTERANRF].EARFCNUL
|
||||
int pmax; // converted from dbM to units of 0.1dBm SQL: db [FAPServiceCellConfigLTERANMobilityIdleModeIntraFreq].[PMax]
|
||||
int ref_sig_power; // converted from dbM to units of 0.1dBm SQL: db This is the DL power per RB [FAPServiceCellConfigLTERANRF].[ReferenceSignalPower]
|
||||
int total_ref_sig_power; // in units of 0.1dB
|
||||
int antenna_gain; // in units of 0.1dB
|
||||
bool limited; // is configured power limited by FAP
|
||||
} device_cfg_params_t;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // PAWS_DAL_CFG_DEVICE_H_
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "spectrum.paws.getSpectrum",
|
||||
"params": {
|
||||
"type": "AVAIL_SPECTRUM_REQ",
|
||||
"version": "1.0",
|
||||
"deviceDesc": {
|
||||
"serialNumber": "M01D201621592159",
|
||||
"manufacturerId": "IPAccess",
|
||||
"modelId": "Radio",
|
||||
"rulesetIds": [
|
||||
"ETSI-EN-301-598-1.1.1"
|
||||
],
|
||||
"etsiEnDeviceType": "A",
|
||||
"etsiEnDeviceCategory": "master",
|
||||
"etsiEnDeviceEmissionsClass": 3,
|
||||
"etsiEnTechnologyId": "AngularJS"
|
||||
},
|
||||
"location": {
|
||||
"point": {
|
||||
"center": {
|
||||
"latitude": 51.507611,
|
||||
"longitude": -0.111162
|
||||
},
|
||||
"semiMajorAxis": 0,
|
||||
"semiMinorAxis": 0,
|
||||
"orientation": 0
|
||||
},
|
||||
"confidence": 95
|
||||
},
|
||||
"antenna": {
|
||||
"height": 15,
|
||||
"heightType": "AGL",
|
||||
"heightUncertainty": 0
|
||||
}
|
||||
},
|
||||
"id": 0
|
||||
}
|
||||
33
software/pawsc/paws/SpectrumDBClient/apps/paws/messages/init_req.json
Executable file
33
software/pawsc/paws/SpectrumDBClient/apps/paws/messages/init_req.json
Executable file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "spectrum.paws.init",
|
||||
"params": {
|
||||
"type": "INIT_REQ",
|
||||
"version": "1.0",
|
||||
"deviceDesc": {
|
||||
"serialNumber": "M01D201621592159",
|
||||
"manufacturerId": "IPAccess",
|
||||
"modelId": "Radio",
|
||||
"rulesetIds": [
|
||||
"ETSI-EN-301-598-1.1.1"
|
||||
],
|
||||
"etsiEnDeviceType": "A",
|
||||
"etsiEnDeviceCategory": "master",
|
||||
"etsiEnDeviceEmissionsClass": 3,
|
||||
"etsiEnTechnologyId": "AngularJS"
|
||||
},
|
||||
"location": {
|
||||
"point": {
|
||||
"center": {
|
||||
"latitude": 51.507611,
|
||||
"longitude": -0.111162
|
||||
},
|
||||
"semiMajorAxis": 0,
|
||||
"semiMinorAxis": 0,
|
||||
"orientation": 0
|
||||
},
|
||||
"confidence": 95
|
||||
}
|
||||
},
|
||||
"id": 0
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "spectrum.paws.getSpectrum",
|
||||
"params": {
|
||||
"type": "AVAIL_SPECTRUM_REQ",
|
||||
"version": "1.0",
|
||||
"deviceDesc": {
|
||||
"serialNumber": "M01D201621592159",
|
||||
"manufacturerId": "IPAccess",
|
||||
"modelId": "Radio",
|
||||
"rulesetIds": [
|
||||
"ETSI-EN-301-598-1.1.1"
|
||||
],
|
||||
"etsiEnDeviceType": "A",
|
||||
"etsiEnDeviceCategory": "master",
|
||||
"etsiEnDeviceEmissionsClass": "4",
|
||||
"etsiEnTechnologyId": "AngularJS"
|
||||
},
|
||||
"location": {
|
||||
"point": {
|
||||
"center": {
|
||||
"latitude": 51.507611,
|
||||
"longitude": -0.111162
|
||||
},
|
||||
"semiMajorAxis": 0,
|
||||
"semiMinorAxis": 0,
|
||||
"orientation": 0
|
||||
},
|
||||
"confidence": 95
|
||||
},
|
||||
"requestType": "Generic Slave"
|
||||
},
|
||||
"id": 0
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "spectrum.paws.getSpectrum",
|
||||
"params": {
|
||||
"type": "AVAIL_SPECTRUM_REQ",
|
||||
"version": "1.0",
|
||||
"deviceDesc": {
|
||||
"serialNumber": "S01D201621592159",
|
||||
"manufacturerId": "IPAccess",
|
||||
"modelId": "Radio",
|
||||
"rulesetIds": [
|
||||
"ETSI-EN-301-598-1.1.1"
|
||||
],
|
||||
"etsiEnDeviceType": "B",
|
||||
"etsiEnDeviceCategory": "slave",
|
||||
"etsiEnDeviceEmissionsClass": 5,
|
||||
"etsiEnTechnologyId": "AngularJS"
|
||||
},
|
||||
"location": {
|
||||
"point": {
|
||||
"center": {
|
||||
"latitude": 51.507611,
|
||||
"longitude": -0.111162
|
||||
},
|
||||
"semiMajorAxis": 0,
|
||||
"semiMinorAxis": 0,
|
||||
"orientation": 0
|
||||
},
|
||||
"confidence": 95
|
||||
},
|
||||
"antenna": {
|
||||
"height": 15,
|
||||
"heightType": "AGL",
|
||||
"heightUncertainty": 0
|
||||
},
|
||||
"masterDeviceDesc": {
|
||||
"serialNumber": "M01D201621592159",
|
||||
"manufacturerId": "IPAccess",
|
||||
"modelId": "Radio",
|
||||
"rulesetIds": [
|
||||
"ETSI-EN-301-598-1.1.1"
|
||||
],
|
||||
"etsiEnDeviceType": "A",
|
||||
"etsiEnDeviceCategory": "master",
|
||||
"etsiEnDeviceEmissionsClass": 3,
|
||||
"etsiEnTechnologyId": "AngularJS"
|
||||
},
|
||||
"masterDeviceLocation": {
|
||||
"point": {
|
||||
"center": {
|
||||
"latitude": 51.507611,
|
||||
"longitude": -0.111162
|
||||
},
|
||||
"semiMajorAxis": 0,
|
||||
"semiMinorAxis": 0,
|
||||
"orientation": 0
|
||||
},
|
||||
"confidence": 95
|
||||
}
|
||||
},
|
||||
"id": 0
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "spectrum.paws.notifySpectrumUse",
|
||||
"id": 0,
|
||||
"params": {
|
||||
"type": "SPECTRUM_USE_NOTIFY",
|
||||
"version": "1.0",
|
||||
"deviceDesc": {
|
||||
"serialNumber": "S01D201621592159",
|
||||
"manufacturerId": "IPAccess",
|
||||
"modelId": "Radio",
|
||||
"rulesetIds": [
|
||||
"ETSI-EN-301-598-1.1.1"
|
||||
],
|
||||
"etsiEnDeviceType": "A",
|
||||
"etsiEnDeviceCategory": "master",
|
||||
"etsiEnDeviceEmissionsClass": 3,
|
||||
"etsiEnTechnologyId": "AngularJS"
|
||||
},
|
||||
"masterDeviceDesc": {
|
||||
"serialNumber": "M01D201621592159",
|
||||
"manufacturerId": "IPAccess",
|
||||
"modelId": "Radio",
|
||||
"rulesetIds": [
|
||||
"ETSI-EN-301-598-1.1.1"
|
||||
],
|
||||
"etsiEnDeviceType": "A",
|
||||
"etsiEnDeviceCategory": "master",
|
||||
"etsiEnDeviceEmissionsClass": 3,
|
||||
"etsiEnTechnologyId": "AngularJS"
|
||||
},
|
||||
"masterDeviceLocation": {
|
||||
"point": {
|
||||
"center": {
|
||||
"latitude": 51.507611,
|
||||
"longitude": -0.111162
|
||||
},
|
||||
"semiMajorAxis": 0,
|
||||
"semiMinorAxis": 0,
|
||||
"orientation": 0
|
||||
},
|
||||
"confidence": 95
|
||||
},
|
||||
"spectra": [ ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "spectrum.paws.notifySpectrumUse",
|
||||
"id": 0,
|
||||
"params": {
|
||||
"type": "SPECTRUM_USE_NOTIFY",
|
||||
"version": "1.0",
|
||||
"deviceDesc": {
|
||||
"serialNumber": "M01D201621592159",
|
||||
"manufacturerId": "IPAccess",
|
||||
"modelId": "Radio",
|
||||
"rulesetIds": [
|
||||
"ETSI-EN-301-598-1.1.1"
|
||||
],
|
||||
"etsiEnDeviceType": "A",
|
||||
"etsiEnDeviceCategory": "master",
|
||||
"etsiEnDeviceEmissionsClass": 3,
|
||||
"etsiEnTechnologyId": "AngularJS"
|
||||
},
|
||||
"location": {
|
||||
"point": {
|
||||
"center": {
|
||||
"latitude": 51.507611,
|
||||
"longitude": -0.111162
|
||||
},
|
||||
"semiMajorAxis": 0,
|
||||
"semiMinorAxis": 0,
|
||||
"orientation": 0
|
||||
},
|
||||
"confidence": 95
|
||||
},
|
||||
"spectra": []
|
||||
}
|
||||
}
|
||||
|
||||
72
software/pawsc/paws/SpectrumDBClient/apps/paws/native/main.c
Normal file
72
software/pawsc/paws/SpectrumDBClient/apps/paws/native/main.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "paws_globals.h"
|
||||
|
||||
#include "lte_db_info.h"
|
||||
#include "paws_db_info.h"
|
||||
#include "sctp_agent_db_info.h"
|
||||
#include "paws_common.h"
|
||||
#include "paws_combiner_sm.h"
|
||||
|
||||
#include "utils/types.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
paws_combiner_sm_t* comb = NULL;
|
||||
uint32_t sctp_agent_port;
|
||||
uint32_t sctp_agent_status_perdiocity;
|
||||
|
||||
if (!(set_paws_db_location("/media/sf_4Gclient/apps/paws/sql_db/paws_native.db")))
|
||||
fatal_error("Cant set PAWS-DB location");
|
||||
|
||||
if (!(set_sctp_agent_db_location("/media/sf_4Gclient/apps/sctp-agent/sql_db/sctp_agent_native.db")))
|
||||
fatal_error("Cant set SCTP-AGENT-DB location");
|
||||
|
||||
if (!(set_lte_db_location("/media/sf_4Gclient/apps/paws/sql_db/femto.db")))
|
||||
fatal_error("Cant set Device-DB location");
|
||||
|
||||
// create the ssl context.
|
||||
if (!(https_init()))
|
||||
fatal_error("Problem in https_init");
|
||||
|
||||
// get the CloudLog settings
|
||||
get_gPawsLoggerSettings();
|
||||
|
||||
// get the DeviceId
|
||||
populate_gDeviceName();
|
||||
|
||||
// loop until the SCTP settings are read correctly
|
||||
while (1)
|
||||
{
|
||||
if ((get_sctp_agent_info(&sctp_agent_port, &sctp_agent_status_perdiocity)))
|
||||
break;
|
||||
sleep(1); // try in a second
|
||||
}
|
||||
|
||||
if (!(comb = paws_combiner_sm_create("combiner", sctp_agent_port, sctp_agent_status_perdiocity)))
|
||||
fatal_error("Cant initialise sytem");
|
||||
|
||||
PUBLIC_FUNC(comb, Run)(comb);
|
||||
|
||||
paws_combiner_sm_free(&comb);
|
||||
|
||||
PawsGlobalsFree();
|
||||
|
||||
// free ssl txt.
|
||||
https_free();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "paws_device_specific.h"
|
||||
|
||||
//#######################################################################################
|
||||
void system_reboot(void)
|
||||
{
|
||||
printf("%s NATIVE \n", __func__);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
bool reboot_device_on_admin_disable(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
3111
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_combiner_sm.c
Executable file
3111
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_combiner_sm.c
Executable file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_SM_COMBINER_H_
|
||||
#define PAWS_SM_COMBINER_H_
|
||||
|
||||
#include "paws_combiner_sm_types.h"
|
||||
|
||||
extern paws_combiner_sm_t* paws_combiner_sm_create(const char* sm_name, uint32_t control_plane_status_port, uint32_t control_plane_status_periodicity);
|
||||
|
||||
extern void paws_combiner_sm_free(paws_combiner_sm_t** paws_combiner_sm);
|
||||
|
||||
#endif // #define PAWS_SM_COMBINER_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_COMBINER_SM_TYPES_H_
|
||||
#define PAWS_COMBINER_SM_TYPES_H_
|
||||
|
||||
#include "state-machine/state-machine.h"
|
||||
#include "https-client/https.h"
|
||||
#include "lists/lists.h"
|
||||
|
||||
#include "paws_types.h"
|
||||
#include "paws_sm_types.h"
|
||||
#include "paws_master_sm_types.h"
|
||||
#include "paws_slave_sm_types.h"
|
||||
|
||||
#include "paws_dal_settings.h"
|
||||
#include "paws_dal_state.h"
|
||||
#include "paws_dal_control_plane.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
paws_sm_func Run;
|
||||
void (*select_DB)(void* sm_, void* caller);
|
||||
void (*DBerror)(void* sm_, void* caller);
|
||||
paws_sm_func LocalDBerror;
|
||||
void (*ProcessDbUpdate)(void* sm_, json_value* new_db_spec);
|
||||
paws_sm_func DlSpectrumNotAvailable;
|
||||
paws_sm_func DlSpectrumAvailable;
|
||||
paws_sm_func UlSpectrumNotAvailable;
|
||||
paws_sm_func UlSpectrumAvailable;
|
||||
paws_sm_func UlSOPSpectrumNotAvailable;
|
||||
void (*UlSOPSpectrumAvailable)(void* sm_, avail_spectrum_t* spectrum_resp, void* caller);
|
||||
paws_sm_func DlNotificationSuccess;
|
||||
paws_sm_func UlNotificationSuccess;
|
||||
void (*setDefaultInfo)(void* sm_, float default_max_location_change, uint32_t default_max_polling_secs);
|
||||
} paws_combiner_public_funcs_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
device_name_t device_name;
|
||||
paws_sop_slave_sm_t* sm;
|
||||
llist_item_t* l_item; // pointer back to entity on list for quicker deletion
|
||||
} sop_slave_sm_entity_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
// slave device info
|
||||
paws_slave_info_t gop_slave_info;
|
||||
paws_slave_info_t sop_slave_info;
|
||||
|
||||
// SMs
|
||||
paws_master_sm_t* paws_master_sm;
|
||||
paws_gop_slave_sm_t* paws_gop_slave_sm;
|
||||
llist_t* sop_sm_list; // list of sop_slave_sm_entity_t
|
||||
|
||||
// SOP min info
|
||||
// the SopMin indicates if a SOP is one of the ones which is used to limit the DLUl powers.
|
||||
// It must be tracked to determine if future processing is needed on a subsequent UlSpectrumAvailable call from that SOP.
|
||||
uint16_t num_sop_min;
|
||||
paws_sop_slave_sm_t* sop_min[MAX_SLAVE_DEVICES]; // list of SM pointers whcih are sop_min
|
||||
|
||||
// DB and DB Discovery stuff
|
||||
paws_db_info_t db_info;
|
||||
paws_db_discovery_info_t db_discovery_info;
|
||||
|
||||
// paws selection config
|
||||
bool paws_settings_read;
|
||||
paws_settings_t paws_settings;
|
||||
|
||||
// pre-boot state info
|
||||
paws_sm_state_info_t* state_info;
|
||||
|
||||
// spectrum states
|
||||
paws_spectrum_state_e dl_spec_state;
|
||||
paws_spectrum_state_e ul_spec_state;
|
||||
ul_dl_spec_cfg_t* ul_dl_spec; // current paired spectrum in use
|
||||
|
||||
// gps
|
||||
uint32_t gps_periodic_duration;
|
||||
paws_gps_location_t gps;
|
||||
|
||||
// master device has been read
|
||||
bool master_info_read;
|
||||
|
||||
// control plane - do we pass Control signalling. When this is false, it is assumed no control is given to the device so it will not be radiating.
|
||||
void* control_plane;
|
||||
bool control_plane_enabled;
|
||||
|
||||
// has a reboot been triggered
|
||||
bool reboot_needed;
|
||||
|
||||
// logger for the DeviceCfg
|
||||
logger_cfg_t DeviceCfg_LogCfg;
|
||||
void* DeviceCfg_Logger; // this is the config for the log messages
|
||||
|
||||
} paws_combiner_private_data_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST ENTRY IN ANY SM WHICH HAS A PAWS_SM.
|
||||
paws_sm_funcs_t paws_sm_func_store;
|
||||
paws_combiner_private_data_t private_data_store;
|
||||
paws_combiner_public_funcs_t public_func_store;
|
||||
control_plane_cfg_t control_plane_cfg;
|
||||
|
||||
paws_sm_t* paws_sm;
|
||||
} paws_combiner_sm_t;
|
||||
|
||||
|
||||
|
||||
#endif // #define PAWS_COMBINER_SM_TYPES_H_
|
||||
|
||||
|
||||
43
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_common.h
Normal file
43
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_common.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_COMMON_H_
|
||||
#define PAWS_COMMON_H_
|
||||
|
||||
|
||||
#include "paws_sm.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
// common macros used by "users" of paws_sm
|
||||
|
||||
#define POPULATE_PAWS_SM_FUNC(sm,fnc) sm->paws_sm_hdr.funcs->fnc = fnc;
|
||||
#define POPULATE_PUBLIC_FUNC(sm,fnc) sm->public_func_store.fnc = fnc;
|
||||
|
||||
#define PAWS_SM_FUNC(sm,fnc) (sm)->paws_sm->local_funcs.fnc // This is used to directly call a paws_sm function even though it might have overridden by this class
|
||||
#define LOCAL_FUNC(sm,fnc) ((paws_sm_t*)sm)->paws_sm_hdr.funcs->fnc // This is used to call a paws_sm function which "might have" been overridden by this class
|
||||
#define PUBLIC_FUNC(sm,fnc) (sm)->public_func_store.fnc
|
||||
#define COMBINER_PUBLIC_FUNC(sm,fnc) PUBLIC_FUNC((paws_combiner_sm_t*)sm, fnc)
|
||||
#define MASTER_PUBLIC_FUNC(sm,fnc) PUBLIC_FUNC((paws_master_sm_t*)sm, fnc)
|
||||
#define GOP_PUBLIC_FUNC(sm,fnc) PUBLIC_FUNC((paws_gop_slave_sm_t*)sm, fnc)
|
||||
#define SOP_PUBLIC_FUNC(sm,fnc) PUBLIC_FUNC((paws_sop_slave_sm_t*)sm, fnc)
|
||||
|
||||
#define GOP_FUNC(sm, fnc) (sm)->gop_slave_hdr.funcs->fnc
|
||||
#define SOP_FUNC(sm, fnc) (sm)->sop_slave_hdr.funcs->fnc
|
||||
|
||||
#define PAWS_SM_DATA(sm) ((paws_sm_t*)sm)->paws_sm_hdr.data
|
||||
#define PAWS_SM_STL_DATA(sm) ((paws_sm_t*)sm)->paws_sm_hdr.stl_data
|
||||
#define PRIVATE_DATA(sm) (sm)->private_data_store
|
||||
|
||||
|
||||
|
||||
#define CREATOR_SM(sm_) ((paws_sm_t*)sm_)->paws_sm_hdr.creator
|
||||
|
||||
|
||||
#define PAWS_LOG_TYPE "PAWS"
|
||||
#define CLOUD_LOGGER_TVWSDB_MSG "TVWSDB-MSG"
|
||||
#define CLOUD_LOGGER_DEVICE_CFG "DEVICE-CFG"
|
||||
|
||||
|
||||
#endif // #define PAWS_COMMON_H_
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
// Platform headers
|
||||
#ifdef _MSC_VER
|
||||
#include <winsock2.h>
|
||||
typedef unsigned socklen_t;
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "paws_dal_control_plane.h"
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
control_plane_cfg_t cfg;
|
||||
int sock;
|
||||
} control_plane_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static int make_outgoing_socket(const char *ip_addr_str, unsigned port)
|
||||
{
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == -1)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
struct sockaddr_in ip_addr = { 0 };
|
||||
ip_addr.sin_family = AF_INET;
|
||||
ip_addr.sin_port = htons(port);
|
||||
if (inet_pton(AF_INET, ip_addr_str, &(ip_addr.sin_addr)) < 0)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
if (connect(sock, &ip_addr, sizeof(ip_addr)) < 0)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
return sock;
|
||||
|
||||
error_hdl:
|
||||
if (sock >= 0) close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void* paws_dal_control_plane_create(control_plane_cfg_t* cfg)
|
||||
{
|
||||
control_plane_t* control_plane = NULL;
|
||||
|
||||
if (!cfg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (((strlen(cfg->status_ipaddr) == 0)) || (cfg->status_port == 0))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// malloc a new control_plane_t
|
||||
if (!(control_plane = malloc(sizeof(control_plane_t))))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memset(control_plane, 0, sizeof(control_plane_t));
|
||||
|
||||
// copy the config
|
||||
memcpy(&control_plane->cfg, cfg, sizeof(control_plane_cfg_t));
|
||||
|
||||
// open the socket
|
||||
control_plane->sock = -1;
|
||||
|
||||
// if this fails, still return control_plane, and attempt to open it when we send data,
|
||||
// This way we can start PAWS before control-plane-agent without any catastrophies
|
||||
control_plane->sock = make_outgoing_socket(cfg->status_ipaddr, cfg->status_port);
|
||||
|
||||
return (void*)control_plane;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void paws_dal_control_plane_free(void** control_plane_)
|
||||
{
|
||||
if (!((control_plane_) && (*control_plane_)))
|
||||
return;
|
||||
|
||||
control_plane_t** control_plane = (control_plane_t**)control_plane_;
|
||||
|
||||
// free the socket
|
||||
if ((*control_plane)->sock >= 0)
|
||||
{
|
||||
close((*control_plane)->sock);
|
||||
(*control_plane)->sock = -1;
|
||||
}
|
||||
|
||||
// free the struct
|
||||
free_and_null(control_plane_);
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_dal_control_plane_send_status(void* control_plane_, bool status)
|
||||
{
|
||||
if (!control_plane_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
control_plane_t* control_plane = (control_plane_t*)control_plane_;
|
||||
|
||||
if (((strlen(control_plane->cfg.status_ipaddr) == 0)) || (control_plane->cfg.status_port == 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (control_plane->sock == -1)
|
||||
{
|
||||
// open the socket
|
||||
if ((control_plane->sock = make_outgoing_socket(control_plane->cfg.status_ipaddr, control_plane->cfg.status_port)) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// try to send a packet
|
||||
size_t num_to_send = sizeof(status);
|
||||
ssize_t num_sent = send(control_plane->sock, &status, num_to_send, MSG_DONTWAIT | MSG_NOSIGNAL);
|
||||
if (num_sent != (ssize_t)num_to_send)
|
||||
{
|
||||
// try again
|
||||
|
||||
// delete and recreate the socket
|
||||
if (control_plane->sock >= 0)
|
||||
{
|
||||
close(control_plane->sock);
|
||||
control_plane->sock = -1;
|
||||
}
|
||||
if ((control_plane->sock = make_outgoing_socket(control_plane->cfg.status_ipaddr, control_plane->cfg.status_port)) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// re-send the data
|
||||
num_sent = send(control_plane->sock, &status, num_to_send, MSG_DONTWAIT | MSG_NOSIGNAL);
|
||||
if (num_sent != (ssize_t)num_to_send)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DAL_CONTROL_PLANE_H_
|
||||
#define PAWS_DAL_CONTROL_PLANE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils/types.h"
|
||||
|
||||
typedef struct {
|
||||
ip_addr_t status_ipaddr;
|
||||
uint32_t status_port;
|
||||
uint32_t status_periodicity;
|
||||
} control_plane_cfg_t;
|
||||
|
||||
extern void* paws_dal_control_plane_create(control_plane_cfg_t* cfg);
|
||||
|
||||
extern void paws_dal_control_plane_free(void** control_plane);
|
||||
|
||||
extern bool paws_dal_control_plane_send_status(void* control_plane, bool status);
|
||||
|
||||
|
||||
#endif // PAWS_DAL_CONTROL_PLANE_H_
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DAL_DATABASE_H_
|
||||
#define PAWS_DAL_DATABASE_H_
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
// This is the PAWS Data Abstraction layer.
|
||||
// It is responsible for reading and writing all data to stroage.
|
||||
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
|
||||
|
||||
|
||||
// *********************************************************************
|
||||
// Database
|
||||
// *********************************************************************
|
||||
|
||||
#define MAX_URL_LENGTH (100)
|
||||
#define MAX_WEBLIST_NAME_LENGTH (30)
|
||||
#define MAX_DB_TOKEN_LENGTH (128)
|
||||
#define MAX_DB_NAME_LENGTH (64)
|
||||
|
||||
typedef char paws_url_t[MAX_URL_LENGTH];
|
||||
typedef char paws_weblist_name_t[MAX_WEBLIST_NAME_LENGTH];
|
||||
typedef char paws_db_token_t[MAX_DB_TOKEN_LENGTH];
|
||||
typedef char paws_db_name_t[MAX_DB_NAME_LENGTH];
|
||||
|
||||
|
||||
typedef struct {
|
||||
paws_url_t host;
|
||||
paws_weblist_name_t fname;
|
||||
} paws_weblist_url_t;
|
||||
|
||||
typedef struct {
|
||||
paws_url_t host;
|
||||
paws_db_token_t token;
|
||||
} paws_db_url_t;
|
||||
|
||||
typedef struct {
|
||||
paws_db_name_t name;
|
||||
paws_url_t url;
|
||||
bool mcwsd_support;
|
||||
bool invalid;
|
||||
} weblist_item_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t refresh_rate;
|
||||
uint16_t num_items;
|
||||
weblist_item_t* items;
|
||||
} paws_weblist_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
paws_db_name_t name;
|
||||
paws_db_url_t db_url;
|
||||
uint8_t valid; // is it present in the weblist
|
||||
time_t barred_utc; // what time was it barred. 0 = not barred
|
||||
} paws_db_item_t;
|
||||
|
||||
#define PAWS_MAX_DB_LIST (10)
|
||||
|
||||
typedef struct {
|
||||
paws_weblist_url_t weblist_url;
|
||||
uint32_t num_db;
|
||||
paws_db_item_t db_list[PAWS_MAX_DB_LIST];
|
||||
} paws_db_info_t;
|
||||
|
||||
|
||||
|
||||
|
||||
// *********************************************************************
|
||||
// Read/write functons
|
||||
// *********************************************************************
|
||||
|
||||
// Return True if read OK.
|
||||
extern bool paws_read_db(paws_db_info_t* db);
|
||||
|
||||
// Return True if written OK.
|
||||
extern bool paws_write_db(paws_db_info_t* db);
|
||||
|
||||
|
||||
|
||||
#endif // PAWS_DAL_GPS_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DAL_DEVICES_H_
|
||||
#define PAWS_DAL_DEVICES_H_
|
||||
|
||||
// This is the PAWS Data Abstraction layer.
|
||||
// It is responsible for reading and writing all data to stroage.
|
||||
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils/types.h"
|
||||
#include "paws_dal_settings.h"
|
||||
#include "paws_dal_gps.h"
|
||||
|
||||
// *********************************************************************
|
||||
// device info
|
||||
// *********************************************************************
|
||||
|
||||
|
||||
#define PAWS_MAX_DEVICE_TECHNOLOGY_LEN (30)
|
||||
#define PAWS_MAX_DEVICE_MANUFACTURER_LEN (30)
|
||||
#define PAWS_MAX_DEVICE_MODEL_LEN (20)
|
||||
#define PAWS_MAX_DEVICE_TYPE_LEN (2)
|
||||
#define PAWS_MAX_DEVICE_CATEGORY_LEN (7)
|
||||
typedef char paws_device_tech_t[PAWS_MAX_DEVICE_TECHNOLOGY_LEN];
|
||||
typedef char paws_device_manufacturer_t[PAWS_MAX_DEVICE_MANUFACTURER_LEN];
|
||||
typedef char paws_device_model_t[PAWS_MAX_DEVICE_MODEL_LEN];
|
||||
typedef char paws_device_type_t[PAWS_MAX_DEVICE_TYPE_LEN];
|
||||
typedef char paws_device_category_t[PAWS_MAX_DEVICE_CATEGORY_LEN];
|
||||
|
||||
|
||||
typedef struct {
|
||||
int gain; // Stored in units of 0.1dB. SQL schema stores it as a float in unts of dB
|
||||
} paws_antenna_info_t;
|
||||
|
||||
typedef struct {
|
||||
paws_device_manufacturer_t manufacturer;
|
||||
paws_device_model_t model;
|
||||
} paws_device_identity_t;
|
||||
|
||||
typedef struct {
|
||||
paws_device_type_t type;
|
||||
paws_device_category_t cat;
|
||||
int emission_class;
|
||||
paws_device_tech_t technology_id;
|
||||
} paws_device_characteristics_t;
|
||||
|
||||
typedef struct {
|
||||
device_name_t unique_id;
|
||||
paws_antenna_info_t antenna_info;
|
||||
paws_device_identity_t device_identity;
|
||||
paws_device_characteristics_t device_characteristics;
|
||||
paws_gps_location_t gps;
|
||||
} paws_device_info_t;
|
||||
|
||||
#define MAX_SLAVE_DEVICES (256)
|
||||
|
||||
typedef struct {
|
||||
uint16_t num_devices;
|
||||
paws_device_info_t device_info[MAX_SLAVE_DEVICES];
|
||||
} paws_slave_info_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool device_enabled; // enable/disable the master
|
||||
int bandwidth;
|
||||
int dl_start_hz;
|
||||
float dl_dbm_per100k;
|
||||
int ul_start_hz;
|
||||
float ul_dbm_per100k;
|
||||
} device_cfg_t;
|
||||
|
||||
|
||||
// *********************************************************************
|
||||
// Read/write functons
|
||||
// *********************************************************************
|
||||
|
||||
// Return True if read OK.
|
||||
extern bool paws_read_master_info(log_app_t app, paws_device_info_t* dev, bool* master_device_cfg_read);
|
||||
|
||||
// Return True if read OK.
|
||||
extern bool paws_read_slave_info(log_app_t app, paws_slave_info_t* gop_slaves, paws_slave_info_t* sop_slaves);
|
||||
|
||||
// get the device Id
|
||||
extern bool paws_get_device_name(device_name_t device_name);
|
||||
|
||||
// Return True if configured OK.
|
||||
// Sets *reboot_needed to True if cfg changes require a reboot
|
||||
extern bool paws_config_master_device(void* logger, device_cfg_t* paws_cfg, bool* admin_state_changed, bool* cfg_changed, bool* reboot_needed, paws_setting_override_t* spectrum_override, paws_antenna_info_t* antenna_info);
|
||||
|
||||
// trigger to reboot the device
|
||||
extern void paws_reboot_master_device(void);
|
||||
|
||||
// Return True if configured OK.
|
||||
// Sets *reboot_needed to True if cfg changes require a reboot
|
||||
extern bool paws_config_master_device_override(void* logger, paws_setting_override_t* spectrum_override, paws_antenna_info_t* antenna_info);
|
||||
|
||||
|
||||
#endif // PAWS_DAL_DEVICES_H_
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DAL_GPS_H_
|
||||
#define PAWS_DAL_GPS_H_
|
||||
|
||||
// This is the PAWS Data Abstraction layer.
|
||||
// It is responsible for reading and writing all data to stroage.
|
||||
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// *********************************************************************
|
||||
// GPS
|
||||
// *********************************************************************
|
||||
|
||||
#define MAX_ANT_HEIGHT_TYPE_LEN (20)
|
||||
typedef char paws_antenna_height_type_t[MAX_ANT_HEIGHT_TYPE_LEN];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
device_name_t device_name;
|
||||
bool fixed; // location has been acquired
|
||||
float latitude;
|
||||
float longitude;
|
||||
uint16_t height;
|
||||
paws_antenna_height_type_t height_type;
|
||||
} paws_gps_location_t;
|
||||
|
||||
|
||||
// *********************************************************************
|
||||
// Read/write functons
|
||||
// *********************************************************************
|
||||
|
||||
// Return True if read OK.
|
||||
extern bool paws_read_gps_from_db(paws_gps_location_t* gps, device_name_t device_name);
|
||||
extern void paws_read_gps(paws_gps_location_t* data, device_name_t device_name);
|
||||
|
||||
#endif // PAWS_DAL_GPS_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DAL_SETTINGS_H_
|
||||
#define PAWS_DAL_SETTINGS_H_
|
||||
|
||||
// This is the PAWS Data Abstraction layer.
|
||||
// It is responsible for reading and writing all data to stroage.
|
||||
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils/types.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
// *********************************************************************
|
||||
// Config
|
||||
// *********************************************************************
|
||||
|
||||
typedef struct {
|
||||
logger_cfg_t app_log;
|
||||
logger_cfg_t msg_log;
|
||||
cloud_logger_cfg_t cloud_log;
|
||||
} paws_setting_loginfo_t;
|
||||
|
||||
typedef struct {
|
||||
bool present;
|
||||
uint16_t bandwidth_rb;
|
||||
uint16_t earfcndl;
|
||||
uint16_t earfcnul;
|
||||
int16_t ref_sig_pwr; // stored in units of 0.1dB
|
||||
int16_t pmax; // stored in units of 0.1dB
|
||||
} paws_setting_override_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// spectrum selected criteria
|
||||
float min_dl_dbm_100k; // min DL dbm per 100k to qualify for selection
|
||||
float min_ul_dbm_100k; // min UL dbm per 100k to qualify for selection
|
||||
// timer info
|
||||
uint16_t db_retry_secs; // how often to retry events (default=15)
|
||||
uint16_t db_barred_secs; // how long to barr a specific DB following failure (default=45)
|
||||
uint16_t setting_periodic_secs; // how often to re-read paws-settings (default=300).
|
||||
uint16_t devices_periodic_secs; // how often to re-read device info (default=60).
|
||||
uint16_t gps_periodic_fast_check_secs; // how often to re-read GPS (default=15). Used when GPS is "NOT" acquired
|
||||
uint16_t gps_periodic_slow_check_secs; // how often to re-read GPS (default=600). Used when GPS "IS" acquired
|
||||
uint32_t max_polling_quick_secs; // quici maxPollingSecs. 0=disable
|
||||
// logging
|
||||
paws_setting_loginfo_t loginfo;
|
||||
// override
|
||||
paws_setting_override_t spectrum_override; // can override the spectrum which the TVWSDB provides in the AVAIL_SPEC_RESP.
|
||||
} paws_settings_t;
|
||||
|
||||
|
||||
// *********************************************************************
|
||||
// Read/write functons
|
||||
// *********************************************************************
|
||||
|
||||
extern bool paws_read_settings(paws_settings_t* settings);
|
||||
|
||||
|
||||
|
||||
#endif // PAWS_DAL_SETTINGS_H_
|
||||
|
||||
144
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_dal_state.h
Normal file
144
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_dal_state.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DAL_STATE_H_
|
||||
#define PAWS_DAL_STATE_H_
|
||||
|
||||
#include "paws_dal_gps.h"
|
||||
#include "paws_dal_database.h"
|
||||
|
||||
#include "lists/lists.h"
|
||||
|
||||
|
||||
// This is the PAWS Data Abstraction layer.
|
||||
// It is responsible for reading and writing all data to stroage.
|
||||
// It is expected that developers will implment individual source for this entity, on a per-platform basis.
|
||||
|
||||
|
||||
// *********************************************************************
|
||||
// PAWS state info.
|
||||
// This is stored prior to reboot, and read post-boot.
|
||||
// *********************************************************************
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t maxPollingSecs;
|
||||
float maxLocationChange;
|
||||
} ruleset_info_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
time_t start_time;
|
||||
time_t stop_time;
|
||||
} time_range_t;
|
||||
|
||||
typedef struct spec_profile_type
|
||||
{
|
||||
uint32_t start_hz;
|
||||
uint32_t end_hz;
|
||||
float dbm;
|
||||
struct spec_profile_type* next;
|
||||
} spec_profile_type_t;
|
||||
|
||||
typedef struct spectrum_schedule
|
||||
{
|
||||
time_range_t event_time_range;
|
||||
spec_profile_type_t* profiles;
|
||||
struct spectrum_schedule* next;
|
||||
uint8_t refcnt; // there can be multiple references, so use this to control the free
|
||||
} spectrum_schedule_t;
|
||||
|
||||
typedef struct spectrum_spec
|
||||
{
|
||||
spectrum_schedule_t* spectrum_schedules;
|
||||
float max_contiguous_bw_hz; // 0 if not present. 0 will mean no constraint
|
||||
float max_contiguous_bw_hz_within_band; // max contiguous actually within band
|
||||
bool needsSpectrumReport; // false if not preset
|
||||
ruleset_info_t ruleset_info;
|
||||
struct spectrum_spec* next;
|
||||
uint8_t refcnt; // there can be multiple references, so use this to control the free
|
||||
} spectrum_spec_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
spectrum_spec_t* spectrum_specs;
|
||||
uint8_t refcnt; // there can be multiple references, so use this to control the free
|
||||
} avail_spectrum_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
spectrum_spec_t* spec;
|
||||
spectrum_schedule_t* sched;
|
||||
uint32_t start_hz;
|
||||
float dbm;
|
||||
uint32_t bandwidth;
|
||||
uint8_t refcnt; // there can be multiple references, so use this to control the free
|
||||
} spec_cfg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
spec_cfg_t* dl_cfg;
|
||||
spec_cfg_t* ul_cfg;
|
||||
uint8_t refcnt; // there can be multiple references, so use this to control the free
|
||||
} ul_dl_spec_cfg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
device_name_t unique_id;
|
||||
int stl_current_state;
|
||||
char* timer_info;
|
||||
float default_max_location_change;
|
||||
uint32_t default_max_polling_secs;
|
||||
float specific_max_location_change;
|
||||
uint32_t specific_max_polling_secs;
|
||||
paws_gps_location_t gps;
|
||||
paws_db_item_t selected_db;
|
||||
avail_spectrum_t* avail_spectrum_resp;
|
||||
spec_cfg_t* available_spectrum;
|
||||
spec_cfg_t* pending_spectrum;
|
||||
spec_cfg_t* selected_spectrum;
|
||||
spec_cfg_t* spectrum_in_use;
|
||||
llist_item_t* l_item;
|
||||
} sm_state_info_t;
|
||||
|
||||
typedef enum {
|
||||
SPEC_STATE_NOT_AVAIL = 0,
|
||||
SPEC_STATE_AVAIL,
|
||||
SPEC_STATE_NOTIFICATION_SUCCESS
|
||||
} paws_spectrum_state_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
paws_weblist_t *wsbd_weblist;
|
||||
int db_discovery_duration;
|
||||
} paws_db_discovery_info_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
paws_spectrum_state_e dl_spec_state;
|
||||
paws_spectrum_state_e ul_spec_state;
|
||||
paws_db_discovery_info_t db_discovery_info;
|
||||
ul_dl_spec_cfg_t* ul_dl_spec;
|
||||
|
||||
llist_t* state_info_ll; // list of sm_state_info_t
|
||||
} paws_sm_state_info_t;
|
||||
|
||||
|
||||
// *********************************************************************
|
||||
// Read/write functons
|
||||
// *********************************************************************
|
||||
|
||||
// Return NULL if empty.
|
||||
extern paws_sm_state_info_t* paws_read_state(void);
|
||||
extern void paws_remove_state(void);
|
||||
|
||||
// Return True if read OK.
|
||||
// state is not to be freed inside function
|
||||
extern bool paws_write_state(paws_sm_state_info_t* state);
|
||||
|
||||
|
||||
#endif // PAWS_DAL_STATE_H_
|
||||
|
||||
|
||||
296
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_dal_types.c
Normal file
296
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_dal_types.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
|
||||
#include "paws_types.h"
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
spectrum_schedule_t* spectrum_sched_new(void)
|
||||
{
|
||||
spectrum_schedule_t* sched = NULL;
|
||||
if ((sched = malloc(sizeof(spectrum_schedule_t))))
|
||||
{
|
||||
memset(sched, 0, sizeof(spectrum_schedule_t));
|
||||
sched->refcnt = 1;
|
||||
return sched;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spectrum_schedule_t* spectrum_sched_vcopy(spectrum_schedule_t* sched)
|
||||
{
|
||||
if (sched)
|
||||
{
|
||||
sched->refcnt++;
|
||||
}
|
||||
return sched;
|
||||
}
|
||||
|
||||
void spectrum_sched_free(spectrum_schedule_t** sched)
|
||||
{
|
||||
if ((sched) && (*sched))
|
||||
{
|
||||
(*sched)->refcnt--;
|
||||
if ((*sched)->refcnt == 0)
|
||||
{
|
||||
spec_profile_type_t* prof = (*sched)->profiles;
|
||||
spec_profile_type_t* next = NULL;
|
||||
while (prof)
|
||||
{
|
||||
next = prof->next;
|
||||
free(prof);
|
||||
prof = next;
|
||||
}
|
||||
free_and_null((void**)sched);
|
||||
}
|
||||
*sched = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
spectrum_spec_t* spectrum_spec_new(void)
|
||||
{
|
||||
spectrum_spec_t* spec = NULL;
|
||||
if ((spec = malloc(sizeof(spectrum_spec_t))))
|
||||
{
|
||||
memset(spec, 0, sizeof(spectrum_spec_t));
|
||||
spec->refcnt = 1;
|
||||
return spec;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spectrum_spec_t* spectrum_spec_vcopy(spectrum_spec_t* spec)
|
||||
{
|
||||
if (spec)
|
||||
{
|
||||
spec->refcnt++;
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
||||
void spectrum_spec_free(spectrum_spec_t** spec)
|
||||
{
|
||||
if ((spec) && (*spec))
|
||||
{
|
||||
(*spec)->refcnt--;
|
||||
if ((*spec)->refcnt == 0)
|
||||
{
|
||||
spectrum_schedule_t* sched = (*spec)->spectrum_schedules;
|
||||
spectrum_schedule_t* next = NULL;
|
||||
while (sched)
|
||||
{
|
||||
next = sched->next;
|
||||
spectrum_sched_free(&sched);
|
||||
sched = next;
|
||||
}
|
||||
free_and_null((void**)spec);
|
||||
}
|
||||
*spec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
|
||||
avail_spectrum_t* avail_spectrum_new(void)
|
||||
{
|
||||
avail_spectrum_t* spec = NULL;
|
||||
if ((spec = malloc(sizeof(avail_spectrum_t))))
|
||||
{
|
||||
memset(spec, 0, sizeof(avail_spectrum_t));
|
||||
spec->refcnt = 1;
|
||||
return spec;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
avail_spectrum_t* avail_spectrum_vcopy(avail_spectrum_t* spec)
|
||||
{
|
||||
if (spec)
|
||||
{
|
||||
spec->refcnt++;
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
||||
void avail_spectrum_free(avail_spectrum_t** avail_spec)
|
||||
{
|
||||
if ((avail_spec) && (*avail_spec))
|
||||
{
|
||||
(*avail_spec)->refcnt--;
|
||||
if ((*avail_spec)->refcnt == 0)
|
||||
{
|
||||
avail_spectrum_t* s = *avail_spec;
|
||||
|
||||
spectrum_spec_t* spec = s->spectrum_specs;
|
||||
spectrum_spec_t* next = NULL;
|
||||
while (spec)
|
||||
{
|
||||
next = spec->next;
|
||||
spectrum_spec_free(&spec);
|
||||
spec = next;
|
||||
}
|
||||
free_and_null((void**)avail_spec);
|
||||
}
|
||||
*avail_spec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
|
||||
spec_cfg_t* spec_cfg_new(void)
|
||||
{
|
||||
spec_cfg_t* cfg = NULL;
|
||||
if ((cfg = malloc(sizeof(spec_cfg_t))))
|
||||
{
|
||||
memset(cfg, 0, sizeof(spec_cfg_t));
|
||||
cfg->refcnt = 1;
|
||||
return cfg;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spec_cfg_t* spec_cfg_vcopy(spec_cfg_t* cfg)
|
||||
{
|
||||
if (cfg)
|
||||
{
|
||||
cfg->refcnt++;
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
void spec_cfg_free(spec_cfg_t** cfg)
|
||||
{
|
||||
if ((cfg) && (*cfg))
|
||||
{
|
||||
(*cfg)->refcnt--;
|
||||
if ((*cfg)->refcnt == 0)
|
||||
{
|
||||
if ((*cfg)->spec)
|
||||
spectrum_spec_free((spectrum_spec_t**)&((*cfg)->spec));
|
||||
if ((*cfg)->sched)
|
||||
spectrum_sched_free((spectrum_schedule_t**)&((*cfg)->sched));
|
||||
free_and_null((void**)cfg);
|
||||
}
|
||||
*cfg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
ul_dl_spec_cfg_t* ul_dl_spec_cfg_new(void)
|
||||
{
|
||||
ul_dl_spec_cfg_t* cfg = NULL;
|
||||
if ((cfg = malloc(sizeof(ul_dl_spec_cfg_t))))
|
||||
{
|
||||
memset(cfg, 0, sizeof(ul_dl_spec_cfg_t));
|
||||
cfg->refcnt = 1;
|
||||
return cfg;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ul_dl_spec_cfg_t* ul_dl_spec_cfg_vcopy(ul_dl_spec_cfg_t* cfg)
|
||||
{
|
||||
if (cfg)
|
||||
{
|
||||
cfg->refcnt++;
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
void ul_dl_spec_cfg_free(ul_dl_spec_cfg_t** cfg)
|
||||
{
|
||||
if ((cfg) && (*cfg))
|
||||
{
|
||||
(*cfg)->refcnt--;
|
||||
if ((*cfg)->refcnt == 0)
|
||||
{
|
||||
if ((*cfg)->dl_cfg)
|
||||
spec_cfg_free(&((*cfg)->dl_cfg));
|
||||
if ((*cfg)->ul_cfg)
|
||||
spec_cfg_free(&((*cfg)->ul_cfg));
|
||||
free_and_null((void**)cfg);
|
||||
}
|
||||
*cfg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
|
||||
sm_state_info_t* sm_state_info_new(void)
|
||||
{
|
||||
sm_state_info_t* info = NULL;
|
||||
if ((info = malloc(sizeof(sm_state_info_t))))
|
||||
{
|
||||
memset(info, 0, sizeof(sm_state_info_t));
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this is used to free from llist too
|
||||
int sm_state_info_free(void* info_)
|
||||
{
|
||||
sm_state_info_t* info = (sm_state_info_t*)info_;
|
||||
|
||||
if (info)
|
||||
{
|
||||
free_and_null((void**)&(info->timer_info));
|
||||
avail_spectrum_free(&info->avail_spectrum_resp);
|
||||
spec_cfg_free(&info->available_spectrum);
|
||||
spec_cfg_free(&info->pending_spectrum);
|
||||
spec_cfg_free(&info->selected_spectrum);
|
||||
spec_cfg_free(&info->spectrum_in_use);
|
||||
free(info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sm_state_info_free_and_null(sm_state_info_t** info)
|
||||
{
|
||||
if ((info) && (*info))
|
||||
{
|
||||
sm_state_info_free((void*)*info);
|
||||
*info = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
paws_sm_state_info_t* paws_sm_state_info_new(void)
|
||||
{
|
||||
paws_sm_state_info_t* info = NULL;
|
||||
if ((info = malloc(sizeof(paws_sm_state_info_t))))
|
||||
{
|
||||
memset(info, 0, sizeof(paws_sm_state_info_t));
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern void paws_sm_state_info_free(paws_sm_state_info_t** info)
|
||||
{
|
||||
if ((info) && (*info))
|
||||
{
|
||||
if ((*info)->ul_dl_spec) ul_dl_spec_cfg_free(&(*info)->ul_dl_spec);
|
||||
llist_free(&(*info)->state_info_ll, sm_state_info_free);
|
||||
free_and_null((void**)info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DAL_TYPES_
|
||||
#define PAWS_DAL_TYPES_
|
||||
|
||||
#include "paws_dal_devices.h"
|
||||
#include "paws_dal_settings.h"
|
||||
#include "paws_dal_state.h"
|
||||
#include "paws_dal_database.h"
|
||||
#include "paws_dal_control_plane.h"
|
||||
|
||||
|
||||
extern spectrum_schedule_t* spectrum_sched_new(void);
|
||||
extern spectrum_schedule_t* spectrum_sched_vcopy(spectrum_schedule_t* sched);
|
||||
extern void spectrum_sched_free(spectrum_schedule_t** sched);
|
||||
|
||||
extern spectrum_spec_t* spectrum_spec_new(void);
|
||||
extern spectrum_spec_t* spectrum_spec_vcopy(spectrum_spec_t* spec);
|
||||
extern void spectrum_spec_free(spectrum_spec_t** spec);
|
||||
|
||||
extern avail_spectrum_t* avail_spectrum_new(void);
|
||||
extern avail_spectrum_t* avail_spectrum_vcopy(avail_spectrum_t* spec);
|
||||
extern void avail_spectrum_free(avail_spectrum_t** avail_spec);
|
||||
|
||||
extern spec_cfg_t* spec_cfg_new(void);
|
||||
extern spec_cfg_t* spec_cfg_vcopy(spec_cfg_t* spec);
|
||||
extern void spec_cfg_free(spec_cfg_t** cfg);
|
||||
|
||||
extern ul_dl_spec_cfg_t* ul_dl_spec_cfg_new(void);
|
||||
extern ul_dl_spec_cfg_t* ul_dl_spec_cfg_vcopy(ul_dl_spec_cfg_t* cfg);
|
||||
extern void ul_dl_spec_cfg_free(ul_dl_spec_cfg_t** cfg);
|
||||
|
||||
extern sm_state_info_t* sm_state_info_new(void);
|
||||
extern int sm_state_info_free(void* info_);
|
||||
extern void sm_state_info_free_and_null(sm_state_info_t** info);
|
||||
|
||||
extern paws_sm_state_info_t* paws_sm_state_info_new(void);
|
||||
extern void paws_sm_state_info_free(paws_sm_state_info_t** info);
|
||||
|
||||
#endif // PAWS_DAL_TYPES_
|
||||
|
||||
|
||||
1086
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_dal_utils.c
Normal file
1086
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_dal_utils.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DAL_UTILS_H_
|
||||
#define PAWS_DAL_UTILS_H_
|
||||
|
||||
#include "json-parser/json.h"
|
||||
|
||||
#include "paws_dal_types.h"
|
||||
|
||||
|
||||
extern char* get_init_paws_dal_encode_str(void);
|
||||
|
||||
extern char* paws_sm_state_info_2_jsonstr(paws_sm_state_info_t* paws_sm_state_info);
|
||||
extern char* paws_db_info_2_jsonstr(paws_db_info_t* db_info);
|
||||
extern bool json_2_paws_db_item(json_value* jval, paws_db_item_t* db_item);
|
||||
|
||||
extern paws_sm_state_info_t* json2_paws_sm_state_info(json_value* jval);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "json-parser/json.h"
|
||||
#include "json-parser/json_utils.h"
|
||||
|
||||
#include "paws_db_info.h"
|
||||
#include "paws_types.h"
|
||||
#include "paws_utils.h"
|
||||
#include "paws_dal_utils.h"
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
#define MAX_SQL_LEN (200)
|
||||
static char sql_str[MAX_SQL_LEN];
|
||||
static char tmp[200];
|
||||
#define SQL_STRCAT(s) strncat(sql_str, s, MAX_SQL_LEN - strlen(sql_str) - 1);
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool sql_get_weblist(sqlite3 *sql_hdl, paws_weblist_url_t* weblist_url)
|
||||
{
|
||||
// get the TVWSDBInfo info
|
||||
sqlite3_stmt *stmt=NULL;
|
||||
char sql[100];
|
||||
sprintf(sql, "SELECT weblist_host, weblist_filename FROM TVWSDBInfo");
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// clear host to start
|
||||
weblist_url->host[0] = '\0';
|
||||
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
char *tmp;
|
||||
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(weblist_url->host, tmp);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(weblist_url->fname, tmp);
|
||||
}
|
||||
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_read_db(paws_db_info_t* db)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
|
||||
if (!db)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
memset(db, 0, sizeof(paws_db_info_t));
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get the weblist info
|
||||
if (!(sql_get_weblist(sql_hdl, &db->weblist_url)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// now get the database entries
|
||||
const char *sql = "SELECT name, host, token, valid, barred_utc FROM TVWSDBInfoDB";
|
||||
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
paws_db_item_t* db_item = &db->db_list[db->num_db] ;
|
||||
char *tmp;
|
||||
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(db_item->name, tmp);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(db_item->db_url.host, tmp);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 2); strcpy(db_item->db_url.token, tmp);
|
||||
db_item->valid = sqlite3_column_int(stmt, 3);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 4);
|
||||
if ((tmp) && (strlen(tmp) > 0))
|
||||
{
|
||||
if ((db_item->barred_utc = timestamp_to_timet(tmp)) == -1)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
db->num_db++;
|
||||
}
|
||||
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
stmt = NULL;
|
||||
|
||||
// free up resources
|
||||
if (sql_hdl)
|
||||
sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
db->num_db = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static paws_db_item_t* get_db_from_dblist(paws_db_item_t* db1, int num_db_in_list, paws_db_item_t* db_list)
|
||||
{
|
||||
for (int i = 0; i < num_db_in_list; i++)
|
||||
{
|
||||
paws_db_item_t* db2 = &db_list[i];
|
||||
|
||||
// they are the same if the url matches
|
||||
if (strcmp(db1->db_url.host, db2->db_url.host) == 0)
|
||||
return db2;
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool sql_add_db_item(paws_db_item_t* db_item)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
char* error_msg = NULL;
|
||||
|
||||
if (!db_item)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// build SQL command
|
||||
sql_str[0] = '\0';
|
||||
SQL_STRCAT("INSERT INTO TVWSDBInfoDB (name, host, token, valid");
|
||||
if (db_item->barred_utc)
|
||||
{
|
||||
SQL_STRCAT(", barred_utc ");
|
||||
}
|
||||
SQL_STRCAT(") VALUES ( ");
|
||||
sprintf(tmp, "'%s', '%s', '%s', %d", db_item->name, db_item->db_url.host, db_item->db_url.token, db_item->valid);
|
||||
SQL_STRCAT(tmp);
|
||||
if (db_item->barred_utc)
|
||||
{
|
||||
SQL_STRCAT(", '");
|
||||
strftime(tmp, sizeof(tmp), "%Y-%m-%dT%H:%M:%SZ", gmtime(&db_item->barred_utc));
|
||||
SQL_STRCAT(tmp);
|
||||
SQL_STRCAT("'");
|
||||
}
|
||||
SQL_STRCAT(");");
|
||||
|
||||
// run command
|
||||
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool sql_update_db_item(paws_db_item_t* db_item)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
char* error_msg = NULL;
|
||||
|
||||
if (!db_item)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// build SQL command
|
||||
sql_str[0] = '\0';
|
||||
sprintf(tmp, "UPDATE TVWSDBInfoDB SET "); SQL_STRCAT(tmp);
|
||||
sprintf(tmp, "name = '%s'", db_item->name); SQL_STRCAT(tmp);
|
||||
sprintf(tmp, ", token = '%s'", db_item->db_url.token); SQL_STRCAT(tmp);
|
||||
sprintf(tmp, ", valid = %d", db_item->valid); SQL_STRCAT(tmp);
|
||||
SQL_STRCAT(", barred_utc='");
|
||||
if (db_item->barred_utc)
|
||||
{
|
||||
strftime(tmp, sizeof(tmp), "%Y-%m-%dT%H:%M:%SZ", gmtime(&db_item->barred_utc));
|
||||
SQL_STRCAT(tmp);
|
||||
}
|
||||
SQL_STRCAT("'");
|
||||
sprintf(tmp, " WHERE host = '%s' ;", db_item->db_url.host); SQL_STRCAT(tmp);
|
||||
|
||||
// run command
|
||||
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool sql_delete_db_item(paws_db_item_t* db_item)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
char* error_msg = NULL;
|
||||
|
||||
if (!db_item)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// build SQL command
|
||||
sprintf(sql_str, "DELETE FROM TVWSDBInfoDB WHERE host = '%s' ;", db_item->db_url.host);
|
||||
// run command
|
||||
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_write_db(paws_db_info_t* db)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
if (!db)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// read the current DB
|
||||
paws_db_info_t curr_db;
|
||||
if (!(paws_read_db(&curr_db)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// add or update DB
|
||||
for (i = 0; i < db->num_db; i++) // walk new db
|
||||
{
|
||||
paws_db_item_t* db_item = &db->db_list[i];
|
||||
paws_db_item_t* curr_db_item = NULL;
|
||||
if (!(curr_db_item = get_db_from_dblist(db_item, curr_db.num_db, &curr_db.db_list[0]))) // if new db is not in curr db list, add it
|
||||
{
|
||||
// it is not there, so add it
|
||||
if (!(sql_add_db_item(db_item)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // if new db is in curr db list, check if it is different, and if so update it
|
||||
// it is there, so update it if different
|
||||
if (memcmp(db_item, curr_db_item, sizeof(paws_db_item_t)) != 0)
|
||||
{
|
||||
// update it
|
||||
if (!(sql_update_db_item(db_item)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete any which have been removed
|
||||
for (i = 0; i < curr_db.num_db; i++) // walk curr db. If any DB from curr_db are not in new db list, delete it from the sql
|
||||
{
|
||||
paws_db_item_t* curr_db_item = &curr_db.db_list[i];
|
||||
paws_db_item_t* new_db_item = NULL;
|
||||
if (!(new_db_item = get_db_from_dblist(curr_db_item, db->num_db, &db->db_list[0]))) // if curr db is not in new db list, delete it
|
||||
{
|
||||
// delete it
|
||||
if (!(sql_delete_db_item(curr_db_item)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "json-parser/json.h"
|
||||
#include "json-parser/json_utils.h"
|
||||
|
||||
#include "paws_globals.h"
|
||||
#include "paws_common.h"
|
||||
#include "paws_db_info.h"
|
||||
#include "paws_types.h"
|
||||
#include "paws_dal_utils.h"
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool sql_get_DeviceInfoAntenna(sqlite3 *sql_hdl, char* deviceid, paws_antenna_info_t* device_ant, bool* antenna_info_read)
|
||||
{
|
||||
*antenna_info_read = false;
|
||||
|
||||
// get the Antenna info
|
||||
sqlite3_stmt *stmt=NULL;
|
||||
char sql[200];
|
||||
sprintf(sql, "SELECT gain FROM DeviceInfoAntenna where deviceid='%s'", deviceid);
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
device_ant->gain = (int)((float)sqlite3_column_double(stmt, 0) * 10.0); // Stored in units of 0.1dB. SQL schema stores it as a float in uints of dB
|
||||
*antenna_info_read = true;
|
||||
}
|
||||
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool sql_get_DeviceInfoId(sqlite3 *sql_hdl, char* deviceid, paws_device_identity_t* device_info_id, bool* device_name_read)
|
||||
{
|
||||
*device_name_read = false;
|
||||
|
||||
// get the Antenna info
|
||||
sqlite3_stmt *stmt=NULL;
|
||||
char sql[100];
|
||||
sprintf(sql, "SELECT manufacturer, model FROM DeviceInfo where deviceid='%s'", deviceid);
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
char *tmp;
|
||||
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(device_info_id->manufacturer, tmp);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(device_info_id->model, tmp);
|
||||
*device_name_read = true;
|
||||
}
|
||||
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_read_master_info(log_app_t app, paws_device_info_t* dev, bool* master_device_cfg_read)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt=NULL;
|
||||
bool device_characteristics_read = false;
|
||||
bool antenna_info_read = false;
|
||||
bool device_name_read = false;
|
||||
|
||||
*master_device_cfg_read = false;
|
||||
|
||||
if (!dev)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
memset(dev, 0, sizeof(paws_device_info_t));
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get the Device Characteristcs for the master device
|
||||
const char *sql = "SELECT deviceid, type, cat, emission_class, technology_id FROM DeviceInfoCharacteristics where cat='master'";
|
||||
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
paws_device_characteristics_t* device_characteristics = &dev->device_characteristics;
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
tmp = (char*)sqlite3_column_text(stmt, 0);
|
||||
if (strcmp(gDeviceName, tmp) != 0)
|
||||
{
|
||||
char log[100];
|
||||
snprintf(log, sizeof(log), "Device mismatch: femto_db='%s' paws_db='%s'", gDeviceName, tmp);
|
||||
logger_log(gPawsAppLogger, log, LOG_ERROR, app, true, true, __FILENAME__, __LINE__, __func__, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
goto error_hdl;
|
||||
}
|
||||
strcpy(dev->unique_id, tmp);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(device_characteristics->type, tmp);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 2); strcpy(device_characteristics->cat, tmp);
|
||||
device_characteristics->emission_class = sqlite3_column_int(stmt, 3);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 4); strcpy(device_characteristics->technology_id, tmp);
|
||||
device_characteristics_read = true;
|
||||
}
|
||||
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
stmt = NULL;
|
||||
|
||||
// get the Antenna info
|
||||
if (device_characteristics_read)
|
||||
{
|
||||
if (!(sql_get_DeviceInfoAntenna(sql_hdl, dev->unique_id, &dev->antenna_info, &antenna_info_read)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
|
||||
// get the Device info
|
||||
if (antenna_info_read)
|
||||
{
|
||||
if (!(sql_get_DeviceInfoId(sql_hdl, dev->unique_id, &dev->device_identity, &device_name_read)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (sql_hdl)
|
||||
sqlite3_close(sql_hdl);
|
||||
|
||||
*master_device_cfg_read = (device_characteristics_read && antenna_info_read && device_name_read);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
*master_device_cfg_read = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_read_slave_info(log_app_t app, paws_slave_info_t* gop_slaves, paws_slave_info_t* sop_slaves)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt=NULL;
|
||||
|
||||
(void)app; // currently unused
|
||||
|
||||
if ((!gop_slaves) || (!sop_slaves))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
memset(gop_slaves, 0, sizeof(paws_slave_info_t));
|
||||
memset(sop_slaves, 0, sizeof(paws_slave_info_t));
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get the Device Characteristcs for the all slave devices
|
||||
const char *sql = "SELECT deviceid, type, cat, emission_class, technology_id FROM DeviceInfoCharacteristics where cat='slave' ORDER BY deviceid";
|
||||
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
paws_device_info_t device;
|
||||
paws_device_info_t* dev = &device;
|
||||
memset(dev, 0, sizeof(paws_device_info_t));
|
||||
|
||||
paws_device_characteristics_t* device_characteristics = &dev->device_characteristics;
|
||||
char *tmp;
|
||||
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(dev->unique_id, tmp);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 1); strcpy(device_characteristics->type, tmp);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 2); strcpy(device_characteristics->cat, tmp);
|
||||
device_characteristics->emission_class = sqlite3_column_int(stmt, 3);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 4); strcpy(device_characteristics->technology_id, tmp);
|
||||
|
||||
bool device_name_read = false;
|
||||
|
||||
// get the Device info
|
||||
if (!(sql_get_DeviceInfoId(sql_hdl, dev->unique_id, &dev->device_identity, &device_name_read)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
if (device_name_read)
|
||||
{
|
||||
// is this SOP - if a GPS is present and fixed it is a SOP slave, else it is a GOP slave
|
||||
bool sop = ((paws_read_gps_from_db(&dev->gps, dev->unique_id)) && (dev->gps.fixed));
|
||||
|
||||
// if this is a GOP but there were previously SOPs counted, move all these SOPS to GOPs
|
||||
if ((!sop) && (sop_slaves->num_devices > 0))
|
||||
{
|
||||
memcpy(&gop_slaves->device_info[gop_slaves->num_devices], &sop_slaves->device_info[0],
|
||||
sizeof(paws_device_info_t) * sop_slaves->num_devices);
|
||||
gop_slaves->num_devices += sop_slaves->num_devices;
|
||||
sop_slaves->num_devices = 0;
|
||||
}
|
||||
|
||||
// if there are any GOPs, we will not run any SOPs, so count SOP as GOP in this case
|
||||
if (sop && (gop_slaves->num_devices == 0))
|
||||
{
|
||||
memcpy(&sop_slaves->device_info[sop_slaves->num_devices], dev, sizeof(paws_device_info_t));
|
||||
sop_slaves->num_devices++;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&gop_slaves->device_info[gop_slaves->num_devices], dev, sizeof(paws_device_info_t));
|
||||
gop_slaves->num_devices++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
stmt = NULL;
|
||||
|
||||
// free up resources
|
||||
if (sql_hdl)
|
||||
sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
sop_slaves->num_devices = 0;
|
||||
gop_slaves->num_devices = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "json-parser/json.h"
|
||||
#include "json-parser/json_utils.h"
|
||||
#include "gps/gps.h"
|
||||
|
||||
#include "paws_db_info.h"
|
||||
#include "paws_types.h"
|
||||
#include "paws_dal_utils.h"
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_read_gps_from_db(paws_gps_location_t* gps, device_name_t device_name)
|
||||
{
|
||||
char **pazResult = NULL;
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
|
||||
gps->fixed = false;
|
||||
|
||||
if (!gps)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
memset(gps, 0, sizeof(paws_gps_location_t));
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
char zSql[100];
|
||||
sprintf(zSql, "SELECT * FROM Gps where deviceid='%s'", device_name);
|
||||
int pnRow; /* Number of result rows written here */
|
||||
int pnColumn; /* Number of result columns written here */
|
||||
char *pzErrmsg = NULL;
|
||||
int rc = sqlite3_get_table(
|
||||
sql_hdl, /* An open database */
|
||||
zSql, /* SQL to be evaluated */
|
||||
&pazResult, /* Results of the query */
|
||||
&pnRow, /* Number of result rows written here */
|
||||
&pnColumn, /* Number of result columns written here */
|
||||
&pzErrmsg /* Error msg written here */
|
||||
);
|
||||
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
if (!((pnRow == 1) && (pnColumn == 6)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
for (int row = 0; row < pnRow; row++)
|
||||
{
|
||||
for (int col = 0; col < pnColumn; col++)
|
||||
{
|
||||
int index = (row * pnColumn) + pnColumn + col;
|
||||
if (strcmp(pazResult[col], "deviceid") == 0)
|
||||
strcpy(gps->device_name, pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "fixed") == 0)
|
||||
gps->fixed =atoi(pazResult[index]) != 0;
|
||||
else if (strcmp(pazResult[col], "latitude") == 0)
|
||||
gps->latitude = (float)atof(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "longitude") == 0)
|
||||
gps->longitude = (float)atof(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "height") == 0)
|
||||
gps->height = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "heightType") == 0)
|
||||
strcpy(gps->height_type, pazResult[index]);
|
||||
else
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (pazResult)
|
||||
sqlite3_free_table(pazResult);
|
||||
if (sql_hdl)
|
||||
sqlite3_close(sql_hdl);
|
||||
|
||||
return gps->fixed;
|
||||
|
||||
error_hdl:
|
||||
if (pazResult) sqlite3_free_table(pazResult);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void paws_read_gps_from_device(paws_gps_location_t* gps, device_name_t device_name)
|
||||
{
|
||||
GpsFixData fix;
|
||||
if (gps_get_fix(&fix) == -1)
|
||||
{
|
||||
gps->fixed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// map from GpsFixData to paws_gps_location_t
|
||||
strcpy(gps->device_name, device_name);
|
||||
gps->fixed = true;
|
||||
gps->latitude = fix.latitude;
|
||||
gps->longitude = fix.longitude;
|
||||
gps->height = fix.altitude;
|
||||
snprintf(gps->height_type, sizeof(paws_antenna_height_type_t), "AMSL");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void paws_read_gps(paws_gps_location_t* gps, device_name_t device_name)
|
||||
{
|
||||
bool ret = paws_read_gps_from_db(gps, device_name);
|
||||
if (!ret)
|
||||
{
|
||||
paws_read_gps_from_device(gps, device_name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "json-parser/json.h"
|
||||
#include "json-parser/json_utils.h"
|
||||
|
||||
#include "paws_db_info.h"
|
||||
#include "paws_types.h"
|
||||
#include "paws_dal_utils.h"
|
||||
|
||||
|
||||
|
||||
// ########################################################################
|
||||
static bool paws_read_settingsCloudLogInfo(sqlite3 *sql_hdl, cloud_logger_cfg_t* log_cfg)
|
||||
{
|
||||
if ((!sql_hdl) || (!log_cfg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memset(log_cfg, 0, sizeof(cloud_logger_cfg_t));
|
||||
|
||||
const char *zSql = "SELECT * FROM SettingsCloudLogInfo";
|
||||
int pnRow; /* Number of result rows written here */
|
||||
int pnColumn; /* Number of result columns written here */
|
||||
char *pzErrmsg = NULL;
|
||||
char **pazResult = NULL;
|
||||
int rc = sqlite3_get_table(
|
||||
sql_hdl, /* An open database */
|
||||
zSql, /* SQL to be evaluated */
|
||||
&pazResult, /* Results of the query */
|
||||
&pnRow, /* Number of result rows written here */
|
||||
&pnColumn, /* Number of result columns written here */
|
||||
&pzErrmsg /* Error msg written here */
|
||||
);
|
||||
|
||||
if (!((rc == SQLITE_OK) && (pnRow == 1) && (pnColumn == 4)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
for (int row = 0; row < pnRow; row++)
|
||||
{
|
||||
for (int col = 0; col < pnColumn; col++)
|
||||
{
|
||||
int index = (row * pnColumn) + pnColumn + col;
|
||||
if (strcmp(pazResult[col], "level") == 0)
|
||||
log_cfg->level = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "logname") == 0)
|
||||
{
|
||||
if (pazResult[index])
|
||||
strcpy(log_cfg->logname, pazResult[index]);
|
||||
}
|
||||
else if (strcmp(pazResult[col], "port") == 0)
|
||||
log_cfg->port = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "cloud_ip") == 0)
|
||||
{
|
||||
if (pazResult[index])
|
||||
strcpy(log_cfg->cloud_addr, pazResult[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (pazResult)
|
||||
sqlite3_free_table(pazResult);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (pazResult) sqlite3_free_table(pazResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ########################################################################
|
||||
static bool paws_read_settingsLogInfo(sqlite3 *sql_hdl, paws_setting_loginfo_t* loginfo)
|
||||
{
|
||||
if ((!sql_hdl) || (!loginfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memset(loginfo, 0, sizeof(paws_setting_loginfo_t));
|
||||
|
||||
// first read the Cloud log
|
||||
if (!(paws_read_settingsCloudLogInfo(sql_hdl, &loginfo->cloud_log)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
|
||||
const char *zSql = "SELECT * FROM SettingsLogInfo";
|
||||
int pnRow; /* Number of result rows written here */
|
||||
int pnColumn; /* Number of result columns written here */
|
||||
char *pzErrmsg = NULL;
|
||||
char **pazResult = NULL;
|
||||
int rc = sqlite3_get_table(
|
||||
sql_hdl, /* An open database */
|
||||
zSql, /* SQL to be evaluated */
|
||||
&pazResult, /* Results of the query */
|
||||
&pnRow, /* Number of result rows written here */
|
||||
&pnColumn, /* Number of result columns written here */
|
||||
&pzErrmsg /* Error msg written here */
|
||||
);
|
||||
|
||||
if (!((rc == SQLITE_OK) && (pnRow == 1) && (pnColumn == 6)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
for (int row = 0; row < pnRow; row++)
|
||||
{
|
||||
for (int col = 0; col < pnColumn; col++)
|
||||
{
|
||||
int index = (row * pnColumn) + pnColumn + col;
|
||||
if (strcmp(pazResult[col], "level") == 0)
|
||||
loginfo->app_log.level = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "logname") == 0)
|
||||
strcpy(loginfo->app_log.logname, pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "tvwsdb_messages_logname") == 0)
|
||||
strcpy(loginfo->msg_log.logname, pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "file_size") == 0)
|
||||
strcpy(loginfo->app_log.size, pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "max_files") == 0)
|
||||
loginfo->app_log.max = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "compress") == 0)
|
||||
loginfo->app_log.compress = atoi(pazResult[index]);
|
||||
else
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loginfo->msg_log.level = loginfo->app_log.level;
|
||||
loginfo->msg_log.level = loginfo->app_log.level;
|
||||
strcpy(loginfo->msg_log.size, loginfo->app_log.size);
|
||||
loginfo->msg_log.max = loginfo->app_log.max;
|
||||
loginfo->msg_log.compress = loginfo->app_log.compress;
|
||||
loginfo->app_log.cloud_level = loginfo->cloud_log.level;
|
||||
loginfo->msg_log.cloud_level = loginfo->cloud_log.level;
|
||||
|
||||
// free up resources
|
||||
if (pazResult)
|
||||
sqlite3_free_table(pazResult);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (pazResult) sqlite3_free_table(pazResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ########################################################################
|
||||
static bool paws_read_settingsSpectrumOverride(sqlite3 *sql_hdl, paws_setting_override_t* override)
|
||||
{
|
||||
if ((!sql_hdl) || (!override))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memset(override, 0, sizeof(paws_setting_override_t));
|
||||
|
||||
const char *zSql = "SELECT * FROM SettingsSpectrumOverride";
|
||||
int pnRow; /* Number of result rows written here */
|
||||
int pnColumn; /* Number of result columns written here */
|
||||
char *pzErrmsg = NULL;
|
||||
char **pazResult = NULL;
|
||||
int rc = sqlite3_get_table(
|
||||
sql_hdl, /* An open database */
|
||||
zSql, /* SQL to be evaluated */
|
||||
&pazResult, /* Results of the query */
|
||||
&pnRow, /* Number of result rows written here */
|
||||
&pnColumn, /* Number of result columns written here */
|
||||
&pzErrmsg /* Error msg written here */
|
||||
);
|
||||
|
||||
if (!(rc == SQLITE_OK))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
if ((pnRow == 1) && (pnColumn == 6))
|
||||
{
|
||||
for (int row = 0; row < pnRow; row++)
|
||||
{
|
||||
for (int col = 0; col < pnColumn; col++)
|
||||
{
|
||||
int index = (row * pnColumn) + pnColumn + col;
|
||||
if (strcmp(pazResult[col], "present") == 0)
|
||||
override->present = atoi(pazResult[index]) != 0;
|
||||
else if (strcmp(pazResult[col], "bandwidth_rb") == 0)
|
||||
override->bandwidth_rb = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "earfcndl") == 0)
|
||||
override->earfcndl = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "earfcnul") == 0)
|
||||
override->earfcnul = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "RefSigPower") == 0)
|
||||
override->ref_sig_pwr = atoi(pazResult[index]) * 10; // convert to units of 0.1dB
|
||||
else if (strcmp(pazResult[col], "PMax") == 0)
|
||||
override->pmax = atoi(pazResult[index]) * 10; // convert to units of 0.1dB
|
||||
else
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// free up resources
|
||||
if (pazResult)
|
||||
sqlite3_free_table(pazResult);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (pazResult) sqlite3_free_table(pazResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_read_settings(paws_settings_t* settings)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
|
||||
if (!settings)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memset(settings, 0, sizeof(paws_settings_t));
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *zSql = "SELECT * FROM Settings";
|
||||
int pnRow; /* Number of result rows written here */
|
||||
int pnColumn; /* Number of result columns written here */
|
||||
char *pzErrmsg=NULL;
|
||||
char **pazResult=NULL;
|
||||
int rc = sqlite3_get_table(
|
||||
sql_hdl, /* An open database */
|
||||
zSql, /* SQL to be evaluated */
|
||||
&pazResult, /* Results of the query */
|
||||
&pnRow, /* Number of result rows written here */
|
||||
&pnColumn, /* Number of result columns written here */
|
||||
&pzErrmsg /* Error msg written here */
|
||||
);
|
||||
|
||||
if (!((rc == SQLITE_OK) && (pnRow == 1) && (pnColumn == 9)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
for (int row = 0; row < pnRow; row++)
|
||||
{
|
||||
for (int col = 0; col < pnColumn; col++)
|
||||
{
|
||||
int index = (row * pnColumn) + pnColumn + col;
|
||||
if (strcmp(pazResult[col], "min_dl_dbm_100k") == 0)
|
||||
settings->min_dl_dbm_100k = (float)atof(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "min_ul_dbm_100k") == 0)
|
||||
settings->min_ul_dbm_100k = (float)atof(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "db_retry_secs") == 0)
|
||||
settings->db_retry_secs = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "db_barred_secs") == 0)
|
||||
settings->db_barred_secs = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "setting_periodic_secs") == 0)
|
||||
settings->setting_periodic_secs = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "devices_periodic_secs") == 0)
|
||||
settings->devices_periodic_secs = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "gps_periodic_fast_check_secs") == 0)
|
||||
settings->gps_periodic_fast_check_secs = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "gps_periodic_slow_check_secs") == 0)
|
||||
settings->gps_periodic_slow_check_secs = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "max_polling_quick_secs") == 0)
|
||||
settings->max_polling_quick_secs = atoi(pazResult[index]);
|
||||
else
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (pazResult)
|
||||
sqlite3_free_table(pazResult);
|
||||
|
||||
if (!(paws_read_settingsLogInfo(sql_hdl, &settings->loginfo)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
if (!(paws_read_settingsSpectrumOverride(sql_hdl, &settings->spectrum_override)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (sql_hdl)
|
||||
sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (pazResult) sqlite3_free_table(pazResult);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "json-parser/json.h"
|
||||
#include "json-parser/json_utils.h"
|
||||
|
||||
#include "paws_db_info.h"
|
||||
#include "paws_types.h"
|
||||
#include "paws_utils.h"
|
||||
#include "paws_dal_utils.h"
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
paws_sm_state_info_t* paws_read_state(void)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
char *json_str=NULL;
|
||||
sqlite3_stmt *stmt=NULL;
|
||||
paws_sm_state_info_t* sm_info = NULL;
|
||||
json_value *jval = NULL;
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get the state
|
||||
const char *sql = "SELECT state_str FROM PreBootState";
|
||||
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
json_str = (char*)sqlite3_column_text(stmt, 0);
|
||||
if (json_str) // if something was read
|
||||
{
|
||||
int len = strlen(json_str);
|
||||
// now convert the json string to a paws_sm_state_info_t
|
||||
// we have the contents, now convert to json
|
||||
if (!(jval = json_parse((json_char*)json_str, len)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
if (!(sm_info = json2_paws_sm_state_info(jval)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (stmt)
|
||||
sqlite3_finalize(stmt);
|
||||
stmt = NULL;
|
||||
if (sql_hdl)
|
||||
sqlite3_close(sql_hdl);
|
||||
if (jval)
|
||||
json_value_free(jval);
|
||||
|
||||
// return the sm info
|
||||
return sm_info;
|
||||
|
||||
error_hdl:
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (jval) json_value_free(jval);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void paws_remove_state(void)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
char* error_msg = NULL;
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// build SQL command
|
||||
char sql_str[100];
|
||||
sprintf(sql_str, "DELETE FROM PreBootState ;");
|
||||
// run command
|
||||
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
error_hdl:
|
||||
// free up resources
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool paws_write_state(paws_sm_state_info_t* sm_state_info)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
char* error_msg = NULL;
|
||||
char* sql_str = NULL;
|
||||
char* p_sql_str = NULL;
|
||||
json_value* jval = NULL;
|
||||
|
||||
sql_str = get_init_paws_dal_encode_str();
|
||||
|
||||
// build SQL command
|
||||
sprintf(sql_str, "INSERT INTO PreBootState (state_str) VALUES ( '");
|
||||
|
||||
// point to where the json is to be written
|
||||
p_sql_str = sql_str + strlen(sql_str);
|
||||
if (!(paws_sm_state_info_2_jsonstr(sm_state_info)))
|
||||
return false;
|
||||
// we have the contents, now convert to json to check it is valid
|
||||
int slen = strlen(p_sql_str);
|
||||
if (!(jval = json_parse((json_char*)p_sql_str, slen)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// append the end
|
||||
p_sql_str += slen;
|
||||
sprintf(p_sql_str, "' ) ;");
|
||||
|
||||
// j contains a valid json string, so write it to the SQL
|
||||
paws_remove_state(); // for safety remove any current state, however there shouldnt actually be any
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_paws_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// run command
|
||||
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (jval) json_value_free(jval);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (jval) json_value_free(jval);
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "paws_db_info.h"
|
||||
|
||||
#define MAX_PAWS_DB_NAME (100)
|
||||
static char g_paws_db[MAX_PAWS_DB_NAME] = "\0";
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool set_paws_db_location(char* db)
|
||||
{
|
||||
if (!db)
|
||||
return false;
|
||||
|
||||
int slen = snprintf(g_paws_db, MAX_PAWS_DB_NAME, "%s", db);
|
||||
if ((slen <= 0) || (slen >= MAX_PAWS_DB_NAME))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
char* get_paws_db_location(void)
|
||||
{
|
||||
return &g_paws_db[0];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef PAWS_DB_INFO_H_
|
||||
#define PAWS_DB_INFO_H_
|
||||
|
||||
extern bool set_paws_db_location(char* db);
|
||||
|
||||
extern char* get_paws_db_location(void);
|
||||
|
||||
|
||||
#endif // PAWS_DB_INFO_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_DEVICE_SPECIFIC_H_
|
||||
#define PAWS_DEVICE_SPECIFIC_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern void system_reboot(void);
|
||||
|
||||
extern bool reboot_device_on_admin_disable(void);
|
||||
|
||||
|
||||
#endif // PAWS_DEVICE_SPECIFIC_H_
|
||||
|
||||
122
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_globals.c
Normal file
122
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_globals.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "paws_globals.h"
|
||||
#include "paws_common.h"
|
||||
#include "paws_dal_settings.h"
|
||||
#include "paws_dal_devices.h"
|
||||
|
||||
// global vars are denoted by a leading 'g'
|
||||
device_name_t gDeviceName = { 0 };
|
||||
void* gPawsAppLogger = NULL;
|
||||
logger_cfg_t gPawsAppLoggerCfg = { 0 };
|
||||
void* gPawsCloudLogger = NULL;
|
||||
static cloud_logger_cfg_t gPawsCloudLoggerCfg = { 0, { 0 }, { 0 }, 0, 0 };
|
||||
paws_reg_domain_e g_paws_reg_domain = PAWS_REGDOMAIN_ETSI;
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void get_gPawsLoggerSettings(void)
|
||||
{
|
||||
paws_settings_t settings;
|
||||
|
||||
if (!(paws_read_settings(&settings)))
|
||||
{
|
||||
fprintf(stderr,"Unable to read settings");
|
||||
return;
|
||||
}
|
||||
|
||||
set_gPawsAppLoggerInfo(&settings.loginfo.app_log);
|
||||
set_gPawsCloudLoggerInfo(&settings.loginfo.cloud_log);
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool set_gPawsAppLoggerInfo(logger_cfg_t* cfg)
|
||||
{
|
||||
if (!cfg)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!gPawsAppLogger) || (memcmp(&gPawsAppLoggerCfg, cfg, sizeof(logger_cfg_t)) != 0)) // if not already created, or config has changed
|
||||
{
|
||||
// copy the new config
|
||||
memcpy(&gPawsAppLoggerCfg, cfg, sizeof(logger_cfg_t));
|
||||
|
||||
// if already created free old one
|
||||
if (gPawsAppLogger)
|
||||
logger_free(&gPawsAppLogger);
|
||||
|
||||
// if there is a filename configured
|
||||
if (strlen(gPawsAppLoggerCfg.logname))
|
||||
{
|
||||
if (!(gPawsAppLogger = logger_create(cfg)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool set_gPawsCloudLoggerInfo(cloud_logger_cfg_t* cfg)
|
||||
{
|
||||
if ((!cfg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!gPawsCloudLogger) || (memcmp(&gPawsCloudLoggerCfg, cfg, sizeof(cloud_logger_cfg_t)) != 0)) // if not already created, or config has changed
|
||||
{
|
||||
// copy the new config
|
||||
memcpy(&gPawsCloudLoggerCfg, cfg, sizeof(cloud_logger_cfg_t));
|
||||
|
||||
// if already created free old one
|
||||
if (gPawsCloudLogger)
|
||||
cloud_logger_free(&gPawsCloudLogger);
|
||||
|
||||
// if there is an IP configured
|
||||
if (strlen(gPawsCloudLoggerCfg.cloud_addr))
|
||||
{
|
||||
if (!(gPawsCloudLogger = cloud_logger_create(cfg)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
extern void populate_gDeviceName(void)
|
||||
{
|
||||
if ((!(paws_get_device_name(gDeviceName))) || (strlen(gDeviceName) < 1))
|
||||
{
|
||||
char log[50];
|
||||
sprintf(log, "%s", "Unable to read DeviceId");
|
||||
logger_log(gPawsAppLogger, log, LOG_ERROR, "Init", true, true, __FILENAME__, __LINE__, __func__, gPawsCloudLogger, gDeviceName, PAWS_LOG_TYPE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void PawsGlobalsFree(void)
|
||||
{
|
||||
if (gPawsAppLogger)
|
||||
logger_free(&gPawsAppLogger);
|
||||
|
||||
if (gPawsCloudLogger)
|
||||
cloud_logger_free(&gPawsCloudLogger);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_GLOBALS_H_
|
||||
#define PAWS_GLOBALS_H_
|
||||
|
||||
#include "utils/types.h"
|
||||
#include "logger/logger.h"
|
||||
#include "logger/cloud_logger.h"
|
||||
|
||||
typedef enum {
|
||||
PAWS_REGDOMAIN_GENERIC=0, // generic PAWS rfc 7545
|
||||
PAWS_REGDOMAIN_ETSI // ETSI 301 598
|
||||
} paws_reg_domain_e;
|
||||
|
||||
|
||||
// global vars
|
||||
extern device_name_t gDeviceName;
|
||||
extern logger_cfg_t gPawsAppLoggerCfg;
|
||||
extern void* gPawsAppLogger;
|
||||
extern void* gPawsCloudLogger;
|
||||
extern paws_reg_domain_e g_paws_reg_domain;
|
||||
|
||||
// prototypes
|
||||
extern void get_gPawsLoggerSettings(void);
|
||||
extern bool set_gPawsAppLoggerInfo(logger_cfg_t* cfg);
|
||||
extern bool set_gPawsCloudLoggerInfo(cloud_logger_cfg_t* cfg);
|
||||
|
||||
|
||||
extern void populate_gDeviceName(void);
|
||||
|
||||
extern void PawsGlobalsFree(void);
|
||||
|
||||
#endif
|
||||
|
||||
558
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_master_sm.c
Normal file
558
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_master_sm.c
Normal file
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "json-parser/json.h"
|
||||
#include "json-parser/json_utils.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
#include "paws_utils.h"
|
||||
#include "paws_master_sm.h"
|
||||
#include "paws_sm.h"
|
||||
#include "paws_common.h"
|
||||
#include "paws_combiner_sm_types.h"
|
||||
#include "paws_messages.h"
|
||||
#include "paws_dal_types.h"
|
||||
|
||||
|
||||
// ##################### Function prototypes
|
||||
// definition of all static class functions called from STL
|
||||
// ---- called privately
|
||||
PAWS_SM_FUNC_PROTO(Init_states);
|
||||
PAWS_SM_FUNC_PROTO(Send_Init_Req);
|
||||
PAWS_SM_FUNC_PROTO(Send_DeviceRegistration);
|
||||
PAWS_SM_FUNC_PROTO(checkAvailableSpectrumDl);
|
||||
PAWS_SM_FUNC_PROTO(Send_AvailableSpectrumReq);
|
||||
PAWS_SM_FUNC_PROTO(Send_Spectrum_Use_Notify);
|
||||
PAWS_SM_FUNC_PROTO(combiner_setDefaultInfo);
|
||||
PAWS_SM_FUNC_PROTO(raiseRegistrationComplete);
|
||||
PAWS_SM_FUNC_PROTO(combiner_DlNotificationSuccess);
|
||||
PAWS_SM_FUNC_PROTO(combiner_DlSpectrumAvailable);
|
||||
PAWS_SM_FUNC_PROTO(combiner_DlSpectrumNotAvailable);
|
||||
// definition of static class functions which are not called directly by STL
|
||||
static void Process_Init_Resp(void* sm_, json_value* resp);
|
||||
static bool init_vars(void* sm_, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs);
|
||||
static bool Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs,
|
||||
logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
|
||||
// public funcs
|
||||
static int run_tick(void* sm_);
|
||||
static void paws_master_private_data_free(paws_master_sm_t* sm_, paws_master_private_data_t* data);
|
||||
|
||||
|
||||
|
||||
// #############################################################################################################################
|
||||
// #############################################################################################################################
|
||||
// ### STL definition
|
||||
|
||||
#define PAWSF(fnc) \
|
||||
static void _##fnc(void* sm) \
|
||||
{\
|
||||
LOCAL_FUNC((paws_master_sm_t*)sm, fnc)(sm); \
|
||||
}
|
||||
|
||||
PAWSF(Start_Retry_Timer)
|
||||
PAWSF(Stop_Retry_Timer)
|
||||
PAWSF(Start_maxPolling_Timer)
|
||||
PAWSF(Start_SpectrumPending_Timer)
|
||||
PAWSF(Stop_SpectrumPending_Timer)
|
||||
PAWSF(Start_SpectrumExpiry_Timer)
|
||||
PAWSF(Stop_SpectrumExpiry_Timer)
|
||||
PAWSF(combiner_selectDB)
|
||||
PAWSF(combiner_DBerror)
|
||||
PAWSF(set_spectrum_InUse)
|
||||
PAWSF(check_spectrum_InUse)
|
||||
PAWSF(clear_spectrum_InUse)
|
||||
PAWSF(activatePendingSpectrum)
|
||||
PAWSF(ActivateSpectrumRuleset)
|
||||
PAWSF(check_Notify_Required)
|
||||
|
||||
|
||||
#define QUO SM_STATE_NO_CHANGE
|
||||
|
||||
|
||||
// ######## STL states
|
||||
#define FOREACH_STATE(STATE) \
|
||||
STATE(INIT) \
|
||||
STATE(DB_SELECT) \
|
||||
STATE(PAWS_INIT) \
|
||||
STATE(DEVICE_REG) \
|
||||
STATE(REQUEST_NEW_SPECTRUM) \
|
||||
STATE(SELECTING_NEW_SPECTRUM) \
|
||||
STATE(SELECTING_NEXT_SPECTRUM) \
|
||||
STATE(SPECTRUM_PENDING) \
|
||||
STATE(SPECTRUM_AVAILABLE) \
|
||||
STATE(SPECTRUM_NOTIFICATION) \
|
||||
STATE(SPECTRUM_ACTIVE) \
|
||||
STATE(NO_SPECTRUM_AVAILABLE) \
|
||||
STATE(MASTER_STATE_END_MARKER)
|
||||
|
||||
// ######## STL events. Note also there are common events also defined in paws_sm.h
|
||||
#define FOREACH_M_EV(EV) \
|
||||
EV(Init_Resp_Received) \
|
||||
EV(Device_reg_Resp_Received) \
|
||||
EV(MASTER_EV_END_MARKER)
|
||||
|
||||
|
||||
|
||||
#define GEN_STATE_ENUM(ENUM) ENUM,
|
||||
#define GEN_STATE_STR(STRING) #STRING,
|
||||
|
||||
enum master_state_e {
|
||||
mDummyState = SM_STATE_START_OF_USER_IDS,
|
||||
FOREACH_STATE(GEN_STATE_ENUM)
|
||||
};
|
||||
|
||||
static const char *master_state_str[] = {
|
||||
"dummy",
|
||||
FOREACH_STATE(GEN_STATE_STR)
|
||||
};
|
||||
|
||||
|
||||
#define GEN_M_EV_ENUM(ENUM) ev_##ENUM,
|
||||
#define GEN_M_EV_STR(STRING) #STRING,
|
||||
|
||||
enum master_event_e {
|
||||
ev_mDummy = ev_PAWS_SM_END_EV_MARKER,
|
||||
FOREACH_M_EV(GEN_M_EV_ENUM)
|
||||
};
|
||||
|
||||
const char *master_ev_str[] = {
|
||||
"dummy",
|
||||
FOREACH_M_EV(GEN_M_EV_STR)
|
||||
};
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
// STL debug functions
|
||||
static const char* state_id_2_str(void* sm_, int id)
|
||||
{
|
||||
UNUSED_PARAM(sm_);
|
||||
|
||||
if ((id > mDummyState) && (id < MASTER_STATE_END_MARKER))
|
||||
{
|
||||
return master_state_str[(id - mDummyState)];
|
||||
}
|
||||
// otherwise its unknown
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static const char* event_id_2_str(void* sm_, int id)
|
||||
{
|
||||
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
|
||||
|
||||
if ((id > ev_mDummy) && (id < ev_MASTER_EV_END_MARKER))
|
||||
{
|
||||
return master_ev_str[(id - ev_mDummy)];
|
||||
}
|
||||
// otherwise call paws_sm
|
||||
return (PAWS_SM_FUNC(sm, event_id_2_str)(sm_, id));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//################################################################################################################################################################################################
|
||||
|
||||
|
||||
/* State-wide State-wide Event specific */
|
||||
/* State 'pre' funcs 'post' funcs Event Next state 'post' funcs */
|
||||
static State state_transition_table[] = {
|
||||
{ INIT , { Init_states }, { NULL }, { { ev_Start, DB_SELECT, { _combiner_selectDB } } } },
|
||||
{ DB_SELECT , { _Start_Retry_Timer}, {_Stop_Retry_Timer }, { { ev_Retry_Timeout, QUO, { _combiner_selectDB,
|
||||
_Start_Retry_Timer } },
|
||||
{ ev_DB_Found, PAWS_INIT, { Send_Init_Req } },
|
||||
{ ev_DB_Updated, PAWS_INIT, { Send_Init_Req } },
|
||||
{ ev_DB_NotFound, QUO, { _Start_Retry_Timer } } } },
|
||||
{ PAWS_INIT , { NULL} , { NULL }, { { ev_DB_Error, DB_SELECT, { _combiner_DBerror,
|
||||
combiner_DlSpectrumNotAvailable } },
|
||||
{ ev_DB_Response_Failure, DB_SELECT, { _combiner_DBerror,
|
||||
combiner_DlSpectrumNotAvailable } },
|
||||
{ ev_Init_Resp_Received, DEVICE_REG, { _Start_maxPolling_Timer,
|
||||
combiner_setDefaultInfo,
|
||||
Send_DeviceRegistration } } } },
|
||||
{ DEVICE_REG , { NULL } , { NULL }, { { ev_DB_Error, DB_SELECT, { _combiner_DBerror,
|
||||
combiner_DlSpectrumNotAvailable } },
|
||||
{ ev_DB_Response_Failure, DB_SELECT, { _combiner_DBerror,
|
||||
combiner_DlSpectrumNotAvailable } },
|
||||
{ ev_Device_reg_Resp_Received, REQUEST_NEW_SPECTRUM, { raiseRegistrationComplete } } } },
|
||||
{ REQUEST_NEW_SPECTRUM , { _combiner_selectDB } , { NULL }, { { ev_DB_Error, QUO, { _combiner_DBerror,
|
||||
_check_spectrum_InUse } },
|
||||
{ ev_DB_Response_Failure, DB_SELECT, { _combiner_DBerror,
|
||||
_check_spectrum_InUse } },
|
||||
{ ev_DB_NotFound, QUO, { _check_spectrum_InUse } },
|
||||
{ ev_DB_Found, QUO, { Send_AvailableSpectrumReq } },
|
||||
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
|
||||
{ ev_SpectrumNotActive, DB_SELECT, { combiner_DlSpectrumNotAvailable } },
|
||||
{ ev_maxPolling_Timeout, QUO, { _combiner_selectDB } },
|
||||
{ ev_maxPollingQuick_Timeout, QUO, { _combiner_selectDB } },
|
||||
{ ev_Available_Spectrum_Resp, SELECTING_NEW_SPECTRUM, { checkAvailableSpectrumDl } } } },
|
||||
{ SELECTING_NEW_SPECTRUM , {NULL } , { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumAvailable, SPECTRUM_AVAILABLE, { NULL } },
|
||||
{ ev_SpectrumPending, SPECTRUM_PENDING, { NULL } },
|
||||
{ ev_SpectrumNotAvailable, NO_SPECTRUM_AVAILABLE, { NULL } } } },
|
||||
{ SELECTING_NEXT_SPECTRUM , { _clear_spectrum_InUse,
|
||||
checkAvailableSpectrumDl }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumAvailable, SPECTRUM_AVAILABLE, { NULL } },
|
||||
{ ev_SpectrumPending, SPECTRUM_PENDING, { NULL } },
|
||||
{ ev_SpectrumNotAvailable, REQUEST_NEW_SPECTRUM, { NULL } } } },
|
||||
{ SPECTRUM_PENDING, { _Start_SpectrumPending_Timer,
|
||||
_check_spectrum_InUse}, {_Stop_SpectrumPending_Timer }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumExpiry_Timeout, QUO, { _clear_spectrum_InUse,
|
||||
combiner_DlSpectrumNotAvailable } },
|
||||
{ ev_SpectrumActive, QUO, { NULL } },
|
||||
{ ev_SpectrumNotActive, QUO, { combiner_DlSpectrumNotAvailable } },
|
||||
{ ev_SpectrumPending_Timeout, SPECTRUM_AVAILABLE, { _activatePendingSpectrum } } } },
|
||||
{ SPECTRUM_AVAILABLE, { _ActivateSpectrumRuleset,
|
||||
_Start_SpectrumExpiry_Timer,
|
||||
combiner_DlSpectrumAvailable }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
|
||||
{ ev_DlUlSpectrumAvailable, SPECTRUM_NOTIFICATION, { NULL } } } },
|
||||
{ SPECTRUM_NOTIFICATION , { _combiner_selectDB }, { NULL }, { { ev_DB_Error, QUO, { _check_spectrum_InUse,
|
||||
_combiner_DBerror } },
|
||||
{ ev_DB_Response_Failure, QUO, { _check_spectrum_InUse,
|
||||
_combiner_DBerror } },
|
||||
{ ev_DB_NotFound, QUO, { _check_spectrum_InUse } },
|
||||
{ ev_DB_Found, QUO, { _check_Notify_Required } },
|
||||
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
|
||||
{ ev_SpectrumNotActive, DB_SELECT, { combiner_DlSpectrumNotAvailable } },
|
||||
{ ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
|
||||
{ ev_Notification_Required, QUO, { Send_Spectrum_Use_Notify } },
|
||||
{ ev_Notification_Not_Required, SPECTRUM_ACTIVE, { _set_spectrum_InUse,
|
||||
combiner_DlNotificationSuccess } },
|
||||
{ ev_Notification_Success, SPECTRUM_ACTIVE, { _set_spectrum_InUse,
|
||||
combiner_DlNotificationSuccess } },
|
||||
{ ev_Notification_Failure, QUO, { _check_spectrum_InUse } } } },
|
||||
{ SPECTRUM_ACTIVE , { NULL }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } } } },
|
||||
{ NO_SPECTRUM_AVAILABLE , { _Stop_SpectrumExpiry_Timer,
|
||||
combiner_DlSpectrumNotAvailable}, { NULL }, { { ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } } } }
|
||||
};
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void Init_states(void* sm_)
|
||||
{
|
||||
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
|
||||
|
||||
paws_master_private_data_free(sm, &(PRIVATE_DATA(sm)));
|
||||
|
||||
// direct call
|
||||
PAWS_SM_FUNC(sm, Init_states)(sm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void Send_Init_Req(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
|
||||
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "----> INIT-REQ MASTER");
|
||||
|
||||
json_value* resp = post_Init_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
|
||||
&(PAWS_SM_DATA((paws_sm_t*)sm)->selected_db.db_url));
|
||||
Process_Init_Resp(sm_, resp);
|
||||
json_value_free(resp);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void Send_DeviceRegistration(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Device_reg_Resp_Received);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void checkAvailableSpectrumDl(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
LOCAL_FUNC(sm_, checkAvailableSpectrum)(sm_);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void Send_AvailableSpectrumReq(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "----> AVAIL-SPEC-REQ MASTER");
|
||||
|
||||
json_value* resp = post_Avail_Spectrum_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
|
||||
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url));
|
||||
// make a note of reception time. This is used to compare time phase with TVWSDB server
|
||||
LOCAL_FUNC(sm_, Process_Available_Spectrum_Resp)(sm_, resp, LTE_DL, time(NULL));
|
||||
json_value_free(resp);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void Send_Spectrum_Use_Notify(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "----> NOTIFY-REQ MASTER");
|
||||
|
||||
json_value* resp = post_Notify_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
|
||||
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url), PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum, 13);
|
||||
LOCAL_FUNC(sm_, Process_Notify_Use_Resp)(sm_, resp);
|
||||
json_value_free(resp);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void combiner_setDefaultInfo(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), setDefaultInfo)(CREATOR_SM(sm_), PAWS_SM_DATA(sm_)->default_max_location_change, PAWS_SM_DATA(sm_)->default_max_polling_secs);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void raiseRegistrationComplete(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void combiner_DlNotificationSuccess(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), DlNotificationSuccess)(CREATOR_SM(sm_));
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void combiner_DlSpectrumAvailable(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), DlSpectrumAvailable)(CREATOR_SM(sm_));
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void combiner_DlSpectrumNotAvailable(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), DlSpectrumNotAvailable)(CREATOR_SM(sm_));
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void Process_Init_Resp(void* sm_, json_value* resp)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
|
||||
|
||||
if (LOCAL_FUNC(sm, Check_HTTP_Result)(sm_, resp, true))
|
||||
{
|
||||
if (LOCAL_FUNC(sm, Check_Valid_Resp)(sm_, resp, true))
|
||||
{
|
||||
// parse the ruleset info
|
||||
json_value* rulesetInfos = NULL;
|
||||
if ((rulesetInfos = json_get(resp, "result/rulesetInfos")))
|
||||
{
|
||||
// walk list of rulesetInfo until we have processed a maxlocationChange param
|
||||
if (rulesetInfos->type == json_array)
|
||||
{
|
||||
int64_t max_polling_secs = 0;
|
||||
double max_location_change = 0;
|
||||
for (uint32_t i=0; i < (rulesetInfos->u.array.length && ((max_location_change==0) || (max_polling_secs == 0))) ; i++)
|
||||
{
|
||||
json_value* ruleset_info = rulesetInfos->u.array.values[i];
|
||||
if (ruleset_info->type == json_object)
|
||||
{
|
||||
if ((json_get_int(ruleset_info, "maxPollingSecs", &max_polling_secs)))
|
||||
{
|
||||
PAWS_SM_DATA(sm)->default_max_polling_secs = max_polling_secs;
|
||||
}
|
||||
if ((json_get_double(ruleset_info, "maxLocationChange", (double*)&max_location_change)))
|
||||
{
|
||||
PAWS_SM_DATA(sm)->default_max_location_change = (float)max_location_change;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "<---- INIT-RESP MASTER");
|
||||
LOCAL_FUNC(sm, raise_)(sm_, (int)ev_Init_Resp_Received);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool init_vars(void* sm_, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
|
||||
|
||||
if (!(PAWS_SM_FUNC(sm, Init)(sm_, min_dbm_100k, db_retry_secs, max_polling_quick_secs)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// store gps
|
||||
LOCAL_FUNC(sm, set_gps)(sm, gps);
|
||||
|
||||
// store fap info
|
||||
LOCAL_FUNC(sm, set_master_info)(sm, master_info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs,
|
||||
logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
|
||||
|
||||
// determine initial state and whether we should run the "pre" functions
|
||||
int initial_state = (sm_state_info) ? sm_state_info->stl_current_state : INIT;
|
||||
bool run_pre = (sm_state_info == NULL);
|
||||
LOG_PRINT(sm_, LOG_INFO, "Initialising STL. state = %s", LOCAL_FUNC(sm_, state_id_2_str)(sm_, initial_state));
|
||||
// generic Init
|
||||
if (!(LOCAL_FUNC(sm, stl_init)(sm_, stl, initial_state, run_pre)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialise variables
|
||||
if (!(init_vars(sm, master_info, gps, min_dbm_100k, db_retry_secs, max_polling_quick_secs)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// create logger
|
||||
LOCAL_FUNC(sm, set_msgLogInfo)(sm_, msg_log_cfg);
|
||||
|
||||
// process pre-boot state
|
||||
if (sm_state_info)
|
||||
{
|
||||
LOCAL_FUNC(sm, process_state_attributes)(sm_, sm_state_info);
|
||||
LOCAL_FUNC(sm, process_state_timers)(sm_, sm_state_info->timer_info);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static int run_tick(void* sm_)
|
||||
{
|
||||
// FUNC_DBG(sm_);
|
||||
|
||||
paws_master_sm_t* sm = (paws_master_sm_t*)sm_;
|
||||
|
||||
// run the timer
|
||||
LOCAL_FUNC(sm, process_next_timer_tick)(sm_);
|
||||
|
||||
// process any triggered events
|
||||
return LOCAL_FUNC(sm, process_events)(sm_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
paws_master_sm_t* paws_master_sm_create(void* creator, const char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs,
|
||||
logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
|
||||
{
|
||||
// FUNC_DBG(sm_);
|
||||
|
||||
paws_master_sm_t* paws_master_sm = NULL;
|
||||
if (!(paws_master_sm = malloc(sizeof(paws_master_sm_t))))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
memset(paws_master_sm, 0, sizeof(paws_master_sm_t));
|
||||
|
||||
// "inherit" the paws_sm
|
||||
if (!(paws_master_sm->paws_sm = paws_sm_create(creator, &paws_master_sm->paws_sm_func_store, sm_name)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
LOG_PRINT(creator, LOG_NOTICE, "Creating MASTER SM");
|
||||
|
||||
// copy the header from the paws_sm
|
||||
memcpy(&paws_master_sm->paws_sm_hdr, &paws_master_sm->paws_sm->paws_sm_hdr, sizeof(paws_sm_header_t));
|
||||
|
||||
// ---- called by paws_sm
|
||||
POPULATE_PAWS_SM_FUNC(paws_master_sm, Init_states);
|
||||
POPULATE_PAWS_SM_FUNC(paws_master_sm, state_id_2_str);
|
||||
POPULATE_PAWS_SM_FUNC(paws_master_sm, event_id_2_str);
|
||||
|
||||
// ---- called publicly
|
||||
POPULATE_PUBLIC_FUNC(paws_master_sm, run_tick);
|
||||
|
||||
// Initialise
|
||||
if (!(Init(paws_master_sm, state_transition_table, master_info, gps, min_dbm_100k, db_retry_secs, msg_log_cfg, max_polling_quick_secs, sm_state_info)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
return paws_master_sm;
|
||||
|
||||
error_hdl:
|
||||
paws_master_sm_free(&paws_master_sm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void paws_master_private_data_free(paws_master_sm_t* sm_, paws_master_private_data_t* data)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
if (data)
|
||||
{
|
||||
// nothing to free
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void paws_master_sm_free(paws_master_sm_t** paws_master_sm)
|
||||
{
|
||||
FUNC_DBG(*paws_master_sm);
|
||||
|
||||
// check that state machine exists
|
||||
if ((paws_master_sm) && (*paws_master_sm))
|
||||
{
|
||||
LOG_PRINT(*paws_master_sm, LOG_NOTICE, "Deleting MASTER SM");
|
||||
|
||||
// free the private data attributes
|
||||
paws_master_private_data_free(*paws_master_sm, &(PRIVATE_DATA(*paws_master_sm)));
|
||||
|
||||
// free the paws_sm
|
||||
// This also free the paws_sm data
|
||||
paws_sm_free(&(**paws_master_sm).paws_sm);
|
||||
|
||||
// free the struct
|
||||
free_and_null((void**)paws_master_sm);
|
||||
}
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_SM_MASTER_H_
|
||||
#define PAWS_SM_MASTER_H_
|
||||
|
||||
#include "paws_master_sm_types.h"
|
||||
|
||||
extern paws_master_sm_t* paws_master_sm_create(void* creator, const char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float min_dbm_100k, uint16_t db_retry_secs,
|
||||
logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
|
||||
extern void paws_master_sm_free(paws_master_sm_t** paws_master_sm);
|
||||
|
||||
#endif // #define PAWS_SM_MASTER_H_
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_MASTER_SM_TYPES_H_
|
||||
#define PAWS_MASTER_SM_TYPES_H_
|
||||
|
||||
#include "paws_sm_types.h"
|
||||
|
||||
typedef struct {
|
||||
int(*run_tick)(void* sm_);
|
||||
} paws_master_public_funcs_t;
|
||||
|
||||
typedef struct {
|
||||
int dummy; // unused
|
||||
} paws_master_private_data_t;
|
||||
|
||||
typedef struct {
|
||||
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
|
||||
paws_sm_funcs_t paws_sm_func_store;
|
||||
paws_master_private_data_t private_data_store;
|
||||
paws_master_public_funcs_t public_func_store;
|
||||
|
||||
paws_sm_t* paws_sm;
|
||||
} paws_master_sm_t;
|
||||
|
||||
|
||||
|
||||
#endif // #define PAWS_MASTER_SM_TYPES_H_
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "paws_message_templates.h"
|
||||
#include "paws_utils.h"
|
||||
#include "paws_common.h"
|
||||
|
||||
// #########################################################################################
|
||||
// ### json templates
|
||||
static char init_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.init\", \"params\": { \"type\": \"INIT_REQ\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } } }, \"id\": 0}";
|
||||
|
||||
|
||||
|
||||
static char available_spectrum_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.getSpectrum\", \"params\": { \"type\": \"AVAIL_SPECTRUM_REQ\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"antenna\": { \"height\": 15, \"heightType\": \"AGL\", \"heightUncertainty\": 0 } }, \"id\": 0}";
|
||||
static char slave_gop_available_spectrum_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.getSpectrum\", \"params\": { \"type\": \"AVAIL_SPECTRUM_REQ\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": \"4\", \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"requestType\": \"Generic Slave\" }, \"id\": 0}";
|
||||
static char slave_sop_available_spectrum_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.getSpectrum\", \"params\": { \"type\": \"AVAIL_SPECTRUM_REQ\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"S01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"B\", \"etsiEnDeviceCategory\": \"slave\", \"etsiEnDeviceEmissionsClass\": 5, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"antenna\": { \"height\": 15, \"heightType\": \"AGL\", \"heightUncertainty\": 0 }, \"masterDeviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"masterDeviceLocation\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } } }, \"id\": 0}";
|
||||
static char spectrum_use_notify_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.notifySpectrumUse\", \"id\": 0, \"params\": { \"type\": \"SPECTRUM_USE_NOTIFY\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"spectra\": [] } }";
|
||||
static char gop_slave_spectrum_use_notify_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.notifySpectrumUse\", \"id\": 0, \"params\": { \"type\": \"SPECTRUM_USE_NOTIFY\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"S01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"slave\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"masterDeviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"masterDeviceLocation\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"spectra\": [ ] } }";
|
||||
static char sop_slave_spectrum_use_notify_req_template[] = "{ \"jsonrpc\": \"2.0\", \"method\": \"spectrum.paws.notifySpectrumUse\", \"id\": 0, \"params\": { \"type\": \"SPECTRUM_USE_NOTIFY\", \"version\": \"1.0\", \"deviceDesc\": { \"serialNumber\": \"S01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"slave\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"masterDeviceDesc\": { \"serialNumber\": \"M01D201621592159\", \"manufacturerId\": \"IPAccess\", \"modelId\": \"Radio\", \"rulesetIds\": [ \"ETSI-EN-301-598-1.1.1\" ], \"etsiEnDeviceType\": \"A\", \"etsiEnDeviceCategory\": \"master\", \"etsiEnDeviceEmissionsClass\": 3, \"etsiEnTechnologyId\": \"AngularJS\" }, \"location\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"masterDeviceLocation\": { \"point\": { \"center\": { \"latitude\": 51.507611, \"longitude\": -0.111162 }, \"semiMajorAxis\": 0, \"semiMinorAxis\": 0, \"orientation\": 0 } }, \"spectra\": [ ] } }";
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static json_value* str2json(void* sm_, char* j_str)
|
||||
{
|
||||
json_value* jval = NULL;
|
||||
|
||||
if ((!j_str) || (strlen(j_str) == 0))
|
||||
{
|
||||
LOG_PRINT(sm_, LOG_ERROR, "Unable to parse data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// we have the contents, now convert to json
|
||||
if (!(jval = json_parse((json_char*)j_str, strlen(j_str))))
|
||||
{
|
||||
LOG_PRINT(sm_, LOG_ERROR, "Unable to parse data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// success
|
||||
return jval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
json_value* get_init_req_template(void* sm_)
|
||||
{
|
||||
return str2json(sm_, init_req_template);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
json_value* get_available_spectrum_req_template(void* sm_)
|
||||
{
|
||||
return str2json(sm_, available_spectrum_req_template);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
json_value* get_slave_gop_available_spectrum_req_template(void* sm_)
|
||||
{
|
||||
return str2json(sm_, slave_gop_available_spectrum_req_template);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
json_value* get_slave_sop_available_spectrum_req_template(void* sm_)
|
||||
{
|
||||
return str2json(sm_, slave_sop_available_spectrum_req_template);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
json_value* get_spectrum_use_notify_req_template(void* sm_)
|
||||
{
|
||||
return str2json(sm_, spectrum_use_notify_req_template);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
json_value* get_gop_slave_spectrum_use_notify_req_template(void* sm_)
|
||||
{
|
||||
return str2json(sm_, gop_slave_spectrum_use_notify_req_template);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
json_value* get_sop_slave_spectrum_use_notify_req_template(void* sm_)
|
||||
{
|
||||
return str2json(sm_, sop_slave_spectrum_use_notify_req_template);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_MESSAGE_TEMPLATES_H_
|
||||
#define PAWS_MESSAGE_TEMPLATES_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "json-parser/json_utils.h"
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
json_value* get_init_req_template(void* sm_);
|
||||
json_value* get_available_spectrum_req_template(void* sm_);
|
||||
json_value* get_slave_gop_available_spectrum_req_template(void* sm_);
|
||||
json_value* get_slave_sop_available_spectrum_req_template(void* sm_);
|
||||
json_value* get_spectrum_use_notify_req_template(void* sm_);
|
||||
json_value* get_gop_slave_spectrum_use_notify_req_template(void* sm_);
|
||||
json_value* get_sop_slave_spectrum_use_notify_req_template(void* sm_);
|
||||
|
||||
|
||||
#endif // PAWS_MESSAGE_TEMPLATES_H_
|
||||
|
||||
|
||||
1274
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_messages.c
Executable file
1274
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_messages.c
Executable file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_MESSAGES_H_
|
||||
#define PAWS_MESSAGES_H_
|
||||
|
||||
#include "gps/gps.h"
|
||||
#include "json-parser/json.h"
|
||||
|
||||
#include "paws_types.h"
|
||||
|
||||
|
||||
// PAWS error codes
|
||||
#define PAWS_ERROR_RESERVED (-100)
|
||||
#define PAWS_ERROR_VERSION (-101)
|
||||
#define PAWS_ERROR_UNSUPPORTED (-102)
|
||||
#define PAWS_ERROR_UNIMPLEMENTED (-103)
|
||||
#define PAWS_ERROR_OUTSIDE_COVERAGE (-104)
|
||||
#define PAWS_ERROR_DATABASE_CHANGE (-105)
|
||||
#define PAWS_ERROR_COMPATIBILITY_MAX PAWS_ERROR_RESERVED
|
||||
#define PAWS_ERROR_COMPATIBILITY_MIN PAWS_ERROR_DATABASE_CHANGE
|
||||
#define PAWS_ERROR_RESERVED2 (-200)
|
||||
#define PAWS_ERROR_MISSING (-201)
|
||||
#define PAWS_ERROR_INVALID_VALUE (-202)
|
||||
#define PAWS_ERROR_REQERROR_MAX PAWS_ERROR_RESERVED2
|
||||
#define PAWS_ERROR_REQERROR_MIN PAWS_ERROR_INVALID_VALUE
|
||||
#define PAWS_ERROR_RESERVED3 (-300)
|
||||
#define PAWS_ERROR_UNAUTHORIZED (-301)
|
||||
#define PAWS_ERROR_NOT_REGISTERED (-302)
|
||||
#define PAWS_ERROR_AUTHORISATION_MAX PAWS_ERROR_RESERVED3
|
||||
#define PAWS_ERROR_AUTHORISATION_MIN PAWS_ERROR_NOT_REGISTERED
|
||||
|
||||
|
||||
#define MAX_DB_ACCESS_ATTEMPTS (5) /* how many to retry a connection before giving up */
|
||||
|
||||
extern json_value* post_Init_Request(void* sm_, paws_device_info_t *device_info, paws_gps_location_t* gps, paws_db_url_t* url);
|
||||
extern json_value* post_Avail_Spectrum_Request(void* sm_, paws_device_info_t *device_info, paws_gps_location_t* gps, paws_db_url_t* url);
|
||||
extern json_value* post_Slave_GOP_Available_Spectrum_Request(void* sm_, paws_device_info_t *device_info, paws_gps_location_t* gps, paws_db_url_t* url);
|
||||
extern json_value* post_Slave_SOP_Available_Spectrum_Request(void* sm_, paws_device_info_t* master_info, paws_device_info_t* slave_device_info, paws_gps_location_t* gps, paws_db_url_t* url);
|
||||
extern json_value* post_Notify_Request(void* sm_, paws_device_info_t *device_info, paws_gps_location_t* gps, paws_db_url_t* url, spec_cfg_t* cfg, uint8_t band_id);
|
||||
extern json_value* post_GOP_slave_Notify_Request(void* sm_, paws_device_info_t* master_info, paws_device_info_t* slave_device_info, paws_gps_location_t* master_gps, paws_db_url_t* url, spec_cfg_t* cfg, uint8_t band_id);
|
||||
extern json_value* post_SOP_slave_Notify_Request(void* sm_, paws_device_info_t* master_info, paws_device_info_t* slave_device_info, paws_gps_location_t* master_gps, paws_db_url_t* url, spec_cfg_t* cfg, uint8_t band_id);
|
||||
|
||||
extern void paws_messages_ssl_free(void* sm_);
|
||||
|
||||
#endif // PAWS_MESSAGES_H_
|
||||
986
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_slave_sm.c
Normal file
986
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_slave_sm.c
Normal file
@@ -0,0 +1,986 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
|
||||
#include "paws_utils.h"
|
||||
#include "paws_slave_sm.h"
|
||||
#include "paws_sm.h"
|
||||
#include "paws_common.h"
|
||||
#include "paws_combiner_sm_types.h"
|
||||
#include "paws_messages.h"
|
||||
|
||||
|
||||
|
||||
// ##################### Function prototypes
|
||||
// definition of all static class functions called from STL
|
||||
// ---- called privately
|
||||
PAWS_SM_FUNC_PROTO(checkAvailableSpectrumUl);
|
||||
PAWS_SM_FUNC_PROTO(combiner_UlSpectrumAvailable);
|
||||
PAWS_SM_FUNC_PROTO(combiner_UlSpectrumNotAvailable);
|
||||
PAWS_SM_FUNC_PROTO(combiner_UlNotificationSuccess);
|
||||
|
||||
static int run_tick(void* sm_);
|
||||
// GOP funcs
|
||||
static void gop_Send_AvailableSpectrumReq(void* sm_);
|
||||
static void gop_Send_Notifications(void* sm_, paws_slave_info_t* slave_info);
|
||||
static void gop_Send_Spectrum_Use_Notify(void* sm_);
|
||||
static void gop_Send_Spectrum_Use_Notify_New(void* sm_);
|
||||
static bool gop_Process_Notify_Use_Resp(void* sm_, json_value* resp);
|
||||
static void gop_set_slaveInfo(void* sm_, paws_slave_info_t* slave_info);
|
||||
static paws_slave_info_t* gop_get_slaveInfo(void* sm_);
|
||||
|
||||
// SOP funcs
|
||||
static void sop_Send_AvailableSpectrumReq(void* sm_);
|
||||
static void sop_Send_Spectrum_Use_Notify(void* sm_);
|
||||
static void sop_Send_Spectrum_Use_Notify_New(void* sm_);
|
||||
static bool sop_Process_Notify_Use_Resp(void* sm_, json_value* resp);
|
||||
static void sop_set_deviceInfo(void* sm_, paws_device_info_t* device_info);
|
||||
static paws_device_info_t* sop_get_deviceInfo(void* sm_);
|
||||
static bool sop_Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
|
||||
paws_device_info_t *device_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
|
||||
|
||||
|
||||
#define SLAVE_FUNC(sm, fnc) ((paws_slave_sm_t*)sm)->slave_hdr.funcs->fnc
|
||||
#define PARENT_SLAVE_FUNC(sm, fnc) (sm)->slave_sm->local_slave_funcs.fnc
|
||||
#define PARENT_SLAVE_SM_FUNC(sm, fnc) (sm)->slave_sm->local_paws_sm_funcs.fnc
|
||||
#define SLAVE_SM_DATA(sm) ((paws_slave_sm_t*)sm)->slave_hdr.data
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// slave_sm
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
|
||||
|
||||
#define PAWSF(fnc) \
|
||||
static void _##fnc(void* sm) \
|
||||
{\
|
||||
LOCAL_FUNC((paws_slave_sm_t*)sm, fnc)(sm); \
|
||||
}
|
||||
|
||||
#define SLAVEF(fnc) \
|
||||
static void _##fnc(void* sm) \
|
||||
{\
|
||||
SLAVE_FUNC((paws_slave_sm_t*)sm, fnc)(sm); \
|
||||
}
|
||||
PAWSF(Clear_Spectrums)
|
||||
PAWSF(Start_Retry_Timer)
|
||||
PAWSF(Stop_Retry_Timer)
|
||||
PAWSF(Start_maxPolling_Timer)
|
||||
PAWSF(Start_SpectrumPending_Timer)
|
||||
PAWSF(Stop_SpectrumPending_Timer)
|
||||
PAWSF(Start_SpectrumExpiry_Timer)
|
||||
PAWSF(Stop_SpectrumExpiry_Timer)
|
||||
PAWSF(combiner_selectDB)
|
||||
PAWSF(combiner_DBerror)
|
||||
PAWSF(set_spectrum_InUse)
|
||||
PAWSF(check_spectrum_InUse)
|
||||
PAWSF(clear_spectrum_InUse)
|
||||
PAWSF(activatePendingSpectrum)
|
||||
PAWSF(ActivateSpectrumRuleset)
|
||||
PAWSF(check_Notify_Required)
|
||||
|
||||
SLAVEF(Send_AvailableSpectrumReq)
|
||||
SLAVEF(Send_Spectrum_Use_Notify)
|
||||
SLAVEF(Send_Spectrum_Use_Notify_New)
|
||||
SLAVEF(combiner_UlSpectrumAvailable)
|
||||
SLAVEF(combiner_UlSpectrumNotAvailable)
|
||||
|
||||
|
||||
|
||||
#define QUO SM_STATE_NO_CHANGE
|
||||
|
||||
// ######## STL states
|
||||
#define FOREACH_STATE(STATE) \
|
||||
STATE(INIT) \
|
||||
STATE(REQUEST_NEW_SPECTRUM) \
|
||||
STATE(WAITING_SPECTRUM_RESP) \
|
||||
STATE(SELECTING_NEW_SPECTRUM) \
|
||||
STATE(SELECTING_NEXT_SPECTRUM) \
|
||||
STATE(SPECTRUM_PENDING) \
|
||||
STATE(SPECTRUM_AVAILABLE) \
|
||||
STATE(SPECTRUM_NOTIFICATION) \
|
||||
STATE(SPECTRUM_ACTIVE) \
|
||||
STATE(NO_SPECTRUM_AVAILABLE) \
|
||||
STATE(SLAVE_STATE_END_MARKER)
|
||||
|
||||
// ######## STL events. Note also there are common events also defined in paws_sm.h
|
||||
#define FOREACH_M_EV(EV) \
|
||||
EV(New_Slave_Info) \
|
||||
EV(SLAVE_EV_END_MARKER)
|
||||
|
||||
|
||||
#define GEN_STATE_ENUM(ENUM) ENUM,
|
||||
#define GEN_STATE_STR(STRING) #STRING,
|
||||
|
||||
enum slave_state_e {
|
||||
sDummyState = SM_STATE_START_OF_USER_IDS,
|
||||
FOREACH_STATE(GEN_STATE_ENUM)
|
||||
};
|
||||
|
||||
static const char *slave_state_str[] = {
|
||||
"dummy",
|
||||
FOREACH_STATE(GEN_STATE_STR)
|
||||
};
|
||||
|
||||
|
||||
#define GEN_M_EV_ENUM(ENUM) ev_##ENUM,
|
||||
#define GEN_M_EV_STR(STRING) #STRING,
|
||||
|
||||
enum slave_event_e {
|
||||
ev_sDummy = ev_PAWS_SM_END_EV_MARKER,
|
||||
FOREACH_M_EV(GEN_M_EV_ENUM)
|
||||
};
|
||||
|
||||
const char *slave_ev_str[] = {
|
||||
"dummy",
|
||||
FOREACH_M_EV(GEN_M_EV_STR)
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
// STL debug functions
|
||||
static const char* state_id_2_str(void* sm_, int id)
|
||||
{
|
||||
UNUSED_PARAM(sm_);
|
||||
|
||||
if ((id > sDummyState) && (id < SLAVE_STATE_END_MARKER))
|
||||
{
|
||||
return slave_state_str[(id - sDummyState)];
|
||||
}
|
||||
// otherwise its unknown
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static const char* event_id_2_str(void* sm_, int id)
|
||||
{
|
||||
paws_slave_sm_t* sm = (paws_slave_sm_t*)sm_;
|
||||
|
||||
if ((id > ev_sDummy) && (id < ev_SLAVE_EV_END_MARKER))
|
||||
{
|
||||
return slave_ev_str[(id - ev_sDummy)];
|
||||
}
|
||||
// otherwise call paws_sm
|
||||
return (PAWS_SM_FUNC(sm, event_id_2_str)(sm_, id));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//################################################################################################################################################################################################
|
||||
|
||||
|
||||
/* State-wide State-wide Event specific */
|
||||
/* State 'pre' funcs 'post' funcs Event Next state 'post' funcs */
|
||||
static State state_transition_table[] = {
|
||||
{ INIT , { _Clear_Spectrums }, { _Stop_Retry_Timer }, { { ev_Start, REQUEST_NEW_SPECTRUM, { _Start_maxPolling_Timer } },
|
||||
{ ev_Retry_Timeout, REQUEST_NEW_SPECTRUM, { NULL } } } },
|
||||
{ REQUEST_NEW_SPECTRUM , { _combiner_selectDB } , { NULL }, { { ev_DB_Error, QUO, { _combiner_DBerror,
|
||||
_check_spectrum_InUse } },
|
||||
{ ev_DB_Response_Failure, QUO, { _combiner_DBerror,
|
||||
_check_spectrum_InUse } },
|
||||
{ ev_DB_NotFound, QUO, { _combiner_DBerror,
|
||||
_check_spectrum_InUse } },
|
||||
{ ev_DB_Found, QUO, { _Send_AvailableSpectrumReq } },
|
||||
{ ev_DB_Updated, QUO, { _Send_AvailableSpectrumReq } },
|
||||
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
|
||||
{ ev_SpectrumNotActive, INIT, { _Start_Retry_Timer,
|
||||
_combiner_UlSpectrumNotAvailable } },
|
||||
{ ev_Retry_Timeout, QUO, { _combiner_selectDB } },
|
||||
{ ev_maxPolling_Timeout, QUO, { _combiner_selectDB } },
|
||||
{ ev_maxPollingQuick_Timeout, QUO, { _combiner_selectDB } },
|
||||
{ ev_Available_Spectrum_Resp, SELECTING_NEW_SPECTRUM, { checkAvailableSpectrumUl } } } },
|
||||
{ WAITING_SPECTRUM_RESP , { NULL } , { NULL }, { { ev_DB_Error, REQUEST_NEW_SPECTRUM, { _check_spectrum_InUse } },
|
||||
{ ev_DB_Response_Failure, REQUEST_NEW_SPECTRUM, { _check_spectrum_InUse } },
|
||||
{ ev_DB_NotFound, REQUEST_NEW_SPECTRUM, { _check_spectrum_InUse } },
|
||||
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
|
||||
{ ev_SpectrumNotActive, INIT, { _Start_Retry_Timer,
|
||||
_combiner_UlSpectrumNotAvailable } },
|
||||
{ ev_Retry_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_Available_Spectrum_Resp, SELECTING_NEW_SPECTRUM, { checkAvailableSpectrumUl } } } },
|
||||
{ SELECTING_NEW_SPECTRUM, {NULL } , { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumAvailable, SPECTRUM_AVAILABLE, { NULL } },
|
||||
{ ev_SpectrumPending, SPECTRUM_PENDING, { NULL } },
|
||||
{ ev_SpectrumNotAvailable, NO_SPECTRUM_AVAILABLE, { NULL } } } },
|
||||
{ SELECTING_NEXT_SPECTRUM , { _clear_spectrum_InUse,
|
||||
checkAvailableSpectrumUl }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumAvailable, SPECTRUM_AVAILABLE, { NULL } },
|
||||
{ ev_SpectrumPending, SPECTRUM_PENDING, { NULL } },
|
||||
{ ev_SpectrumNotAvailable, REQUEST_NEW_SPECTRUM, { NULL } } } },
|
||||
{ SPECTRUM_PENDING, { _Start_SpectrumPending_Timer,
|
||||
_check_spectrum_InUse}, {_Stop_SpectrumPending_Timer }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumExpiry_Timeout, QUO, { _clear_spectrum_InUse,
|
||||
_combiner_UlSpectrumNotAvailable } },
|
||||
{ ev_SpectrumActive, QUO, { NULL } },
|
||||
{ ev_SpectrumNotActive, QUO, { _combiner_UlSpectrumNotAvailable } },
|
||||
{ ev_SpectrumPending_Timeout, SPECTRUM_AVAILABLE, { _activatePendingSpectrum } } } },
|
||||
{ SPECTRUM_AVAILABLE, { _ActivateSpectrumRuleset,
|
||||
_Start_SpectrumExpiry_Timer,
|
||||
_combiner_UlSpectrumAvailable }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
|
||||
{ ev_DlUlSpectrumAvailable, SPECTRUM_NOTIFICATION, { NULL } } } },
|
||||
{ SPECTRUM_NOTIFICATION , { _check_Notify_Required }, { NULL }, { { ev_DB_Error, INIT, { _combiner_DBerror,
|
||||
_check_spectrum_InUse } },
|
||||
{ ev_DB_Response_Failure, QUO, { _combiner_DBerror,
|
||||
_check_spectrum_InUse } },
|
||||
{ ev_DB_NotFound, QUO, { _combiner_DBerror,
|
||||
_check_spectrum_InUse } },
|
||||
{ ev_SpectrumActive, SPECTRUM_ACTIVE, { NULL } },
|
||||
{ ev_SpectrumNotActive, INIT, { _Start_Retry_Timer,
|
||||
_combiner_UlSpectrumNotAvailable } },
|
||||
{ ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
|
||||
|
||||
{ ev_Notification_Required, QUO, { _Send_Spectrum_Use_Notify } },
|
||||
{ ev_Notification_Not_Required, SPECTRUM_ACTIVE, { _set_spectrum_InUse,
|
||||
combiner_UlNotificationSuccess } },
|
||||
{ ev_Notification_Success, SPECTRUM_ACTIVE, { _set_spectrum_InUse,
|
||||
combiner_UlNotificationSuccess } },
|
||||
{ ev_Notification_Failure, QUO, { _check_spectrum_InUse } } } },
|
||||
{ SPECTRUM_ACTIVE , { NULL }, { NULL }, { { ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } },
|
||||
{ ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_SpectrumExpiry_Timeout, SELECTING_NEXT_SPECTRUM, { NULL } },
|
||||
{ ev_New_Slave_Info, QUO, { _check_Notify_Required } },
|
||||
{ ev_Notification_Required, QUO, { _Send_Spectrum_Use_Notify_New } } } },
|
||||
{ NO_SPECTRUM_AVAILABLE , { _Stop_SpectrumExpiry_Timer,
|
||||
_combiner_UlSpectrumNotAvailable}, { NULL }, { { ev_maxPolling_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_maxPollingQuick_Timeout, REQUEST_NEW_SPECTRUM, { NULL } },
|
||||
{ ev_GPS_location_changed, REQUEST_NEW_SPECTRUM, { _clear_spectrum_InUse } } } }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void checkAvailableSpectrumUl(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
LOCAL_FUNC(sm_, checkAvailableSpectrum)(sm_);
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void combiner_UlSpectrumAvailable(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlSpectrumAvailable)(CREATOR_SM(sm_));
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void combiner_UlSpectrumNotAvailable(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlSpectrumNotAvailable)(CREATOR_SM(sm_));
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void combiner_UlNotificationSuccess(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlNotificationSuccess)(CREATOR_SM(sm_));
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void Start(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Start);
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static int run_tick(void* sm_)
|
||||
{
|
||||
// FUNC_DBG(sm_);
|
||||
|
||||
paws_slave_sm_t* sm = (paws_slave_sm_t*)sm_;
|
||||
|
||||
// run the timer
|
||||
LOCAL_FUNC(sm, process_next_timer_tick)(sm_);
|
||||
|
||||
// process any triggered events
|
||||
return LOCAL_FUNC(sm, process_events)(sm_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool init_vars(void* sm_, paws_device_info_t* set_master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
|
||||
float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
paws_slave_sm_t* sm = (paws_slave_sm_t*)sm_;
|
||||
|
||||
if (!(PAWS_SM_FUNC(sm, Init)(sm_, min_dbm_100k, db_retry_secs, max_polling_quick_secs)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// store gps
|
||||
LOCAL_FUNC(sm, set_gps)(sm, gps);
|
||||
|
||||
// store fap info
|
||||
LOCAL_FUNC(sm, set_master_info)(sm, set_master_info);
|
||||
|
||||
// default info
|
||||
LOCAL_FUNC(sm, set_defaultInfo)(sm_, default_max_location_change, default_max_polling_secs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool slave_Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
|
||||
float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
paws_slave_sm_t* sm = (paws_slave_sm_t*)sm_;
|
||||
|
||||
// determine initial state and whether we should run the "pre" functions
|
||||
int initial_state = (sm_state_info) ? sm_state_info->stl_current_state : INIT;
|
||||
bool run_pre = (sm_state_info == NULL);
|
||||
|
||||
LOG_PRINT(sm_, LOG_INFO, "Initialising STL. state = %s", LOCAL_FUNC(sm_, state_id_2_str)(sm_, initial_state));
|
||||
// generic Init
|
||||
if (!(LOCAL_FUNC(sm, stl_init)(sm_, stl, initial_state, run_pre)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialise variables
|
||||
if (!(init_vars(sm, master_info, gps, default_max_location_change, default_max_polling_secs, min_dbm_100k, db_retry_secs, max_polling_quick_secs)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// create logger
|
||||
LOCAL_FUNC(sm, set_msgLogInfo)(sm_, msg_log_cfg);
|
||||
|
||||
// process pre-boot state
|
||||
if (sm_state_info)
|
||||
{
|
||||
LOCAL_FUNC(sm, process_state_attributes)(sm_, sm_state_info);
|
||||
LOCAL_FUNC(sm, process_state_timers)(sm_, sm_state_info->timer_info);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void paws_slave_sm_data_free(paws_slave_sm_t* sm_, paws_slave_sm_data_t* data)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
if (data)
|
||||
{
|
||||
// nothing to free
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void paws_slave_sm_free(paws_slave_sm_t** paws_slave_sm)
|
||||
{
|
||||
FUNC_DBG(*paws_slave_sm);
|
||||
|
||||
// check that state machine exists
|
||||
if ((paws_slave_sm) && (*paws_slave_sm))
|
||||
{
|
||||
// free the private data attributes
|
||||
paws_slave_sm_data_free(*paws_slave_sm, SLAVE_SM_DATA(*paws_slave_sm));
|
||||
|
||||
// free the paws_sm
|
||||
// This also free the paws_sm data
|
||||
paws_sm_free(&(**paws_slave_sm).paws_sm);
|
||||
|
||||
// free the struct
|
||||
free_and_null((void**)paws_slave_sm);
|
||||
}
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
|
||||
#define S_POPULATE_PAWS_SM_FUNC(sm,fnc) \
|
||||
sm->paws_sm_hdr.funcs->fnc = fnc; \
|
||||
sm->local_paws_sm_funcs.fnc = fnc;
|
||||
|
||||
#define POPULATE_SLAVE_FUNC(sm,fnc) \
|
||||
sm->slave_hdr.funcs->fnc = fnc; \
|
||||
sm->local_slave_funcs.fnc = fnc;
|
||||
|
||||
#define POPULATE_SLAVE_FUNC2(sm,fnc,fname) \
|
||||
sm->slave_hdr.funcs->fnc = fname; \
|
||||
sm->local_slave_funcs.fnc = fname;
|
||||
|
||||
#define S_POPULATE_PUBLIC_FUNC(sm,fnc) \
|
||||
sm->slave_hdr.public_funcs->fnc = fnc; \
|
||||
sm->local_public_funcs.fnc = fnc;
|
||||
|
||||
static paws_slave_sm_t* paws_slave_sm_create(void* creator, paws_sm_funcs_t* paws_sm_funcs, paws_slave_sm_funcs_t* slave_funcs, paws_slave_public_funcs_t* public_funcs, char* sm_name)
|
||||
{
|
||||
// FUNC_DBG(sm_);
|
||||
|
||||
paws_slave_sm_t* paws_slave_sm = NULL;
|
||||
if (!(paws_slave_sm = malloc(sizeof(paws_slave_sm_t))))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
memset(paws_slave_sm, 0, sizeof(paws_slave_sm_t));
|
||||
|
||||
paws_slave_sm->slave_hdr.funcs = slave_funcs;
|
||||
paws_slave_sm->slave_hdr.public_funcs = public_funcs;
|
||||
paws_slave_sm->slave_hdr.data = &paws_slave_sm->slave_data_store;
|
||||
|
||||
// "inherit" the paws_sm
|
||||
if (!(paws_slave_sm->paws_sm = paws_sm_create(creator, paws_sm_funcs, sm_name)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// copy the header from the paws_sm
|
||||
memcpy(&paws_slave_sm->paws_sm_hdr, &paws_slave_sm->paws_sm->paws_sm_hdr, sizeof(paws_sm_header_t));
|
||||
|
||||
// ---- called by paws_sm
|
||||
// for safety, copy the parent paws sm first, then overwrite
|
||||
memcpy(&paws_slave_sm->local_paws_sm_funcs, paws_slave_sm->paws_sm_hdr.funcs, sizeof(paws_sm_funcs_t));
|
||||
S_POPULATE_PAWS_SM_FUNC(paws_slave_sm, event_id_2_str);
|
||||
S_POPULATE_PAWS_SM_FUNC(paws_slave_sm, state_id_2_str);
|
||||
// ---- slave funcs
|
||||
POPULATE_SLAVE_FUNC2(paws_slave_sm, Init, slave_Init);
|
||||
POPULATE_SLAVE_FUNC(paws_slave_sm, init_vars);
|
||||
POPULATE_SLAVE_FUNC(paws_slave_sm, checkAvailableSpectrumUl);
|
||||
POPULATE_SLAVE_FUNC(paws_slave_sm, combiner_UlSpectrumAvailable);
|
||||
POPULATE_SLAVE_FUNC(paws_slave_sm, combiner_UlSpectrumNotAvailable);
|
||||
POPULATE_SLAVE_FUNC(paws_slave_sm, combiner_UlNotificationSuccess);
|
||||
// ---- public funcs
|
||||
S_POPULATE_PUBLIC_FUNC(paws_slave_sm, Start);
|
||||
S_POPULATE_PUBLIC_FUNC(paws_slave_sm, run_tick);
|
||||
|
||||
return paws_slave_sm;
|
||||
|
||||
error_hdl:
|
||||
paws_slave_sm_free(&paws_slave_sm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// GOP
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void gop_Send_AvailableSpectrumReq(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "----> AVAIL-SPEC-REQ GOP");
|
||||
|
||||
json_value* resp = post_Slave_GOP_Available_Spectrum_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
|
||||
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url));
|
||||
LOCAL_FUNC(sm_, Process_Available_Spectrum_Resp)(sm_, resp, LTE_UL, time(NULL));
|
||||
json_value_free(resp);
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void gop_Send_Notifications(void* sm_, paws_slave_info_t* slave_info)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
paws_device_info_t* device = NULL;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < slave_info->num_devices; i++)
|
||||
{
|
||||
device = &slave_info->device_info[i];
|
||||
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "----> NOTIFY-REQ GOP(device = %s)", device->unique_id);
|
||||
|
||||
json_value* resp = post_GOP_slave_Notify_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), device, &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
|
||||
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url), PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum, 13);
|
||||
|
||||
if (!(SLAVE_FUNC(sm_, Process_Notify_Use_Resp(sm_,resp))))
|
||||
{
|
||||
// Nothing defined
|
||||
|
||||
// possible enhancement is to block slave
|
||||
|
||||
}
|
||||
json_value_free(resp);
|
||||
}
|
||||
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Notification_Success);
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void gop_Send_Spectrum_Use_Notify(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
paws_gop_slave_sm_t* sm = (paws_gop_slave_sm_t*)sm_;
|
||||
|
||||
if ((!PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum))
|
||||
{
|
||||
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_DB_NotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
SLAVE_FUNC(sm_, Send_Notifications(sm_, &PRIVATE_DATA(sm).slave_info));
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void gop_Send_Spectrum_Use_Notify_New(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static bool gop_Process_Notify_Use_Resp(void* sm_, json_value* resp)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
if (LOCAL_FUNC(sm_, Check_HTTP_Result)(sm_, resp, false))
|
||||
{
|
||||
if (LOCAL_FUNC(sm_, Check_Valid_Resp)(sm_, resp, false))
|
||||
{
|
||||
// raise event to show a valid RESP was received
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "<---- NOTIFY-RESP");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void gop_set_slaveInfo(void* sm_, paws_slave_info_t* slave_info)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
paws_gop_slave_sm_t* sm = (paws_gop_slave_sm_t*)sm_;
|
||||
memcpy(&(PRIVATE_DATA(sm).slave_info), slave_info, sizeof(paws_slave_info_t));
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static paws_slave_info_t* gop_get_slaveInfo(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
paws_gop_slave_sm_t* sm = (paws_gop_slave_sm_t*)sm_;
|
||||
return &PRIVATE_DATA(sm).slave_info;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool gop_Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs, paws_slave_info_t* slave_info,
|
||||
float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
|
||||
{
|
||||
paws_gop_slave_sm_t* sm = (paws_gop_slave_sm_t*)sm_;
|
||||
|
||||
// Initialise
|
||||
if (!(PARENT_SLAVE_FUNC(sm, Init)(sm_, stl, master_info, gps, default_max_location_change, default_max_polling_secs, min_dbm_100k, db_retry_secs, msg_log_cfg, max_polling_quick_secs, sm_state_info)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// GOP specific
|
||||
GOP_FUNC(sm, set_slaveInfo)(sm, slave_info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
|
||||
#define POPULATE_GOP_SLAVE_FUNC(sm,fnc) sm->slave_hdr.funcs->fnc = gop_##fnc;
|
||||
|
||||
#define POPULATE_GOP_PUBLIC_FUNC(sm,fnc) sm->slave_hdr.public_funcs->fnc = gop_##fnc;
|
||||
|
||||
#define POPULATE_GOP_SPECIFIC_FUNC(sm,fnc) sm->gop_slave_hdr.funcs->fnc = gop_##fnc;
|
||||
|
||||
paws_gop_slave_sm_t* paws_gop_slave_sm_create(void* creator, char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
|
||||
paws_slave_info_t *slave_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
|
||||
{
|
||||
// FUNC_DBG(sm_);
|
||||
|
||||
paws_gop_slave_sm_t* paws_gop_slave_sm = NULL;
|
||||
|
||||
if (!(paws_gop_slave_sm = malloc(sizeof(paws_gop_slave_sm_t))))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
memset(paws_gop_slave_sm, 0, sizeof(paws_gop_slave_sm_t));
|
||||
|
||||
// "inherit" the slave_sm
|
||||
if (!(paws_gop_slave_sm->slave_sm = paws_slave_sm_create(creator, &paws_gop_slave_sm->paws_sm_func_store, &paws_gop_slave_sm->slave_func_store, &paws_gop_slave_sm->public_func_store, sm_name )))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// copy the paws_header from the slave_sm
|
||||
memcpy(&paws_gop_slave_sm->paws_sm_hdr, &paws_gop_slave_sm->slave_sm->paws_sm_hdr, sizeof(paws_sm_header_t));
|
||||
// copy the slave header
|
||||
memcpy(&paws_gop_slave_sm->slave_hdr, &paws_gop_slave_sm->slave_sm->slave_hdr, sizeof(slave_sm_header_t));
|
||||
// copy the paws_sm
|
||||
paws_gop_slave_sm->paws_sm = paws_gop_slave_sm->slave_sm->paws_sm;
|
||||
|
||||
LOG_PRINT(creator, LOG_NOTICE, "Creating GOP SM");
|
||||
|
||||
|
||||
// populate functions
|
||||
// ---- paws_sm funcs
|
||||
// --------none
|
||||
// ---- slave funcs
|
||||
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_AvailableSpectrumReq);
|
||||
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_AvailableSpectrumReq);
|
||||
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_Spectrum_Use_Notify);
|
||||
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_Spectrum_Use_Notify_New);
|
||||
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Send_Notifications);
|
||||
POPULATE_GOP_SLAVE_FUNC(paws_gop_slave_sm, Process_Notify_Use_Resp);
|
||||
// ---- public funcs
|
||||
// --------none
|
||||
// GOP-specific funcs
|
||||
paws_gop_slave_sm->gop_slave_hdr.funcs = &paws_gop_slave_sm->gop_func_store;
|
||||
POPULATE_GOP_SPECIFIC_FUNC(paws_gop_slave_sm, set_slaveInfo);
|
||||
POPULATE_GOP_SPECIFIC_FUNC(paws_gop_slave_sm, get_slaveInfo);
|
||||
|
||||
// Initialise
|
||||
if (!(gop_Init(paws_gop_slave_sm, state_transition_table, master_info, gps, default_max_location_change, default_max_polling_secs, slave_info, min_dbm_100k, db_retry_secs,
|
||||
msg_log_cfg, max_polling_quick_secs, sm_state_info)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
return paws_gop_slave_sm;
|
||||
|
||||
error_hdl:
|
||||
paws_gop_slave_sm_free(&paws_gop_slave_sm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void paws_gop_sm_data_free(paws_gop_slave_sm_t* sm_, paws_gop_private_data_t* data)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
if (data)
|
||||
{
|
||||
// nothing to free
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void paws_gop_slave_sm_free(paws_gop_slave_sm_t** paws_gop_slave_sm)
|
||||
{
|
||||
FUNC_DBG(*paws_gop_slave_sm);
|
||||
|
||||
// check that state machine exists
|
||||
if ((paws_gop_slave_sm) && (*paws_gop_slave_sm))
|
||||
{
|
||||
LOG_PRINT(*paws_gop_slave_sm, LOG_NOTICE, "Deleting GOP SM");
|
||||
|
||||
// free the private data attributes
|
||||
paws_gop_sm_data_free(*paws_gop_slave_sm, &(PRIVATE_DATA(*paws_gop_slave_sm)));
|
||||
|
||||
// free the slace_sm
|
||||
paws_slave_sm_free(&(**paws_gop_slave_sm).slave_sm);
|
||||
|
||||
// free the struct
|
||||
free_and_null((void**)paws_gop_slave_sm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// SOP
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
// #######################################################################################################################
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void sop_Send_AvailableSpectrumReq(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
|
||||
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "----> AVAIL-SPEC-REQ SOP (device=%s)", PRIVATE_DATA(sm).device_info.unique_id);
|
||||
|
||||
json_value* resp = post_Slave_SOP_Available_Spectrum_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &PRIVATE_DATA(sm).device_info, &PRIVATE_DATA(sm).device_info.gps,
|
||||
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url));
|
||||
LOCAL_FUNC(sm_, Process_Available_Spectrum_Resp)(sm_, resp, LTE_UL, time(NULL));
|
||||
json_value_free(resp);
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void sop_Send_Spectrum_Use_Notify(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
|
||||
|
||||
if ((!PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum))
|
||||
{
|
||||
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_DB_NotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "----> NOTIFY-REQ SOP (device=%s)", PRIVATE_DATA(sm).device_info.unique_id);
|
||||
|
||||
json_value* resp = post_SOP_slave_Notify_Request(sm_, &(PAWS_SM_DATA((paws_sm_t*)sm_)->master_info), &PRIVATE_DATA(sm).device_info, &(PAWS_SM_DATA((paws_sm_t*)sm_)->gps),
|
||||
&(PAWS_SM_DATA((paws_sm_t*)sm_)->selected_db.db_url), PAWS_SM_DATA((paws_sm_t*)sm_)->selected_spectrum, 13);
|
||||
|
||||
if (!(SLAVE_FUNC(sm_, Process_Notify_Use_Resp(sm_, resp))))
|
||||
{
|
||||
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Notification_Failure);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOCAL_FUNC(sm_, raise_)(sm_, (int)ev_Notification_Success);
|
||||
}
|
||||
json_value_free(resp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void sop_Send_Spectrum_Use_Notify_New(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static bool sop_Process_Notify_Use_Resp(void* sm_, json_value* resp)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
if (LOCAL_FUNC(sm_, Check_HTTP_Result)(sm_, resp, false))
|
||||
{
|
||||
if (LOCAL_FUNC(sm_, Check_Valid_Resp)(sm_, resp, false))
|
||||
{
|
||||
// raise event to show a valid RESP was received
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "<---- NOTIFY-RESP");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void sop_set_deviceInfo(void* sm_, paws_device_info_t* device_info)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
|
||||
memcpy(&(PRIVATE_DATA(sm).device_info), device_info, sizeof(paws_device_info_t));
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static paws_device_info_t* sop_get_deviceInfo(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
|
||||
return &PRIVATE_DATA(sm).device_info;
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void sop_combiner_UlSpectrumAvailable(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
|
||||
|
||||
avail_spectrum_t* spectrum_resp = LOCAL_FUNC(sm, GetAvailSpectrumResp)(sm);
|
||||
|
||||
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlSOPSpectrumAvailable)(CREATOR_SM(sm_), spectrum_resp, sm_);
|
||||
}
|
||||
|
||||
//#######################################################################################
|
||||
static void sop_combiner_UlSpectrumNotAvailable(void* sm_)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
COMBINER_PUBLIC_FUNC(CREATOR_SM(sm_), UlSOPSpectrumNotAvailable)(CREATOR_SM(sm_));
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool sop_Init(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
|
||||
paws_device_info_t *device_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
|
||||
{
|
||||
paws_sop_slave_sm_t* sm = (paws_sop_slave_sm_t*)sm_;
|
||||
|
||||
// Initialise
|
||||
if (!(PARENT_SLAVE_FUNC(sm, Init)(sm_, stl, master_info, gps, default_max_location_change, default_max_polling_secs, min_dbm_100k, db_retry_secs, msg_log_cfg, max_polling_quick_secs, sm_state_info)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// SOP specific
|
||||
SOP_FUNC(sm, set_deviceInfo)(sm, device_info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
|
||||
#define POPULATE_SOP_SLAVE_FUNC(sm,fnc) sm->slave_hdr.funcs->fnc = sop_##fnc;
|
||||
|
||||
#define POPULATE_SOP_PUBLIC_FUNC(sm,fnc) sm->slave_hdr.public_funcs->fnc = sop_##fnc;
|
||||
|
||||
#define POPULATE_SOP_SPECIFIC_FUNC(sm,fnc) sm->sop_slave_hdr.funcs->fnc = sop_##fnc;
|
||||
|
||||
paws_sop_slave_sm_t* paws_sop_slave_sm_create(void* creator, char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
|
||||
paws_device_info_t *device_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info)
|
||||
{
|
||||
// FUNC_DBG(sm_);
|
||||
|
||||
paws_sop_slave_sm_t* paws_sop_slave_sm = NULL;
|
||||
|
||||
if (!(paws_sop_slave_sm = malloc(sizeof(paws_sop_slave_sm_t))))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
memset(paws_sop_slave_sm, 0, sizeof(paws_sop_slave_sm_t));
|
||||
|
||||
// "inherit" the slave_sm
|
||||
if (!(paws_sop_slave_sm->slave_sm = paws_slave_sm_create(creator, &paws_sop_slave_sm->paws_sm_func_store, &paws_sop_slave_sm->slave_func_store, &paws_sop_slave_sm->public_func_store, sm_name)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// copy the paws_header from the slave_sm
|
||||
memcpy(&paws_sop_slave_sm->paws_sm_hdr, &paws_sop_slave_sm->slave_sm->paws_sm_hdr, sizeof(paws_sm_header_t));
|
||||
// copy the slave header
|
||||
memcpy(&paws_sop_slave_sm->slave_hdr, &paws_sop_slave_sm->slave_sm->slave_hdr, sizeof(slave_sm_header_t));
|
||||
// copy the paws_sm
|
||||
paws_sop_slave_sm->paws_sm = paws_sop_slave_sm->slave_sm->paws_sm;
|
||||
|
||||
LOG_PRINT(creator, LOG_NOTICE, "Creating SOP SM [%s]", sm_name);
|
||||
|
||||
// populate functions
|
||||
// ---- paws_sm funcs
|
||||
// --------none
|
||||
// ---- slave funcs
|
||||
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Send_AvailableSpectrumReq);
|
||||
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Send_AvailableSpectrumReq);
|
||||
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Send_Spectrum_Use_Notify);
|
||||
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Send_Spectrum_Use_Notify_New);
|
||||
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, Process_Notify_Use_Resp);
|
||||
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, combiner_UlSpectrumAvailable);
|
||||
POPULATE_SOP_SLAVE_FUNC(paws_sop_slave_sm, combiner_UlSpectrumNotAvailable);
|
||||
|
||||
// ---- public funcs
|
||||
|
||||
// --------none
|
||||
// GOP-specific funcs
|
||||
paws_sop_slave_sm->sop_slave_hdr.funcs = &paws_sop_slave_sm->sop_func_store;
|
||||
POPULATE_SOP_SPECIFIC_FUNC(paws_sop_slave_sm, set_deviceInfo);
|
||||
POPULATE_SOP_SPECIFIC_FUNC(paws_sop_slave_sm, get_deviceInfo);
|
||||
|
||||
// Initialise
|
||||
if (!(sop_Init(paws_sop_slave_sm, state_transition_table, master_info, gps, default_max_location_change, default_max_polling_secs, device_info, min_dbm_100k, db_retry_secs,
|
||||
msg_log_cfg, max_polling_quick_secs, sm_state_info)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
return paws_sop_slave_sm;
|
||||
|
||||
error_hdl:
|
||||
paws_sop_slave_sm_free(&paws_sop_slave_sm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void paws_sop_sm_data_free(paws_sop_slave_sm_t* sm_, paws_sop_private_data_t* data)
|
||||
{
|
||||
FUNC_DBG(sm_);
|
||||
|
||||
if (data)
|
||||
{
|
||||
// nothing to free
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void paws_sop_slave_sm_free(paws_sop_slave_sm_t** paws_sop_slave_sm)
|
||||
{
|
||||
FUNC_DBG(*paws_sop_slave_sm);
|
||||
|
||||
// check that state machine exists
|
||||
if ((paws_sop_slave_sm) && (*paws_sop_slave_sm))
|
||||
{
|
||||
LOG_PRINT(*paws_sop_slave_sm, LOG_NOTICE, "Deleting SOP SM [%s]", (*paws_sop_slave_sm)->paws_sm_hdr.unique_id);
|
||||
|
||||
// free the private data attributes
|
||||
paws_sop_sm_data_free(*paws_sop_slave_sm, &(PRIVATE_DATA(*paws_sop_slave_sm)));
|
||||
|
||||
// free the slace_sm
|
||||
paws_slave_sm_free(&(**paws_sop_slave_sm).slave_sm);
|
||||
|
||||
// free the struct
|
||||
free_and_null((void**)paws_sop_slave_sm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_SM_SLAVE_H_
|
||||
#define PAWS_SM_SLAVE_H_
|
||||
|
||||
#include "paws_slave_sm_types.h"
|
||||
|
||||
extern paws_gop_slave_sm_t* paws_gop_slave_sm_create(void* creator, char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
|
||||
paws_slave_info_t *slave_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
|
||||
extern void paws_gop_slave_sm_free(paws_gop_slave_sm_t** paws_gop_slave_sm);
|
||||
|
||||
extern paws_sop_slave_sm_t* paws_sop_slave_sm_create(void* creator, char* sm_name, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs,
|
||||
paws_device_info_t *device_info, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
|
||||
extern void paws_sop_slave_sm_free(paws_sop_slave_sm_t** paws_sop_slave_sm);
|
||||
|
||||
#endif // #define PAWS_SM_SLAVE_H_
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_SLAVE_SM_TYPES_H_
|
||||
#define PAWS_SLAVE_SM_TYPES_H_
|
||||
|
||||
#include "paws_sm_types.h"
|
||||
|
||||
typedef struct {
|
||||
bool (*Init)(void* sm_, State* stl, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs, float min_dbm_100k, uint16_t db_retry_secs, logger_cfg_t* msg_log_cfg, uint32_t max_polling_quick_secs, sm_state_info_t* sm_state_info);
|
||||
bool (*init_vars)(void* sm_, paws_device_info_t* master_info, paws_gps_location_t* gps, float default_max_location_change, uint32_t default_max_polling_secs, float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs);
|
||||
paws_sm_func checkAvailableSpectrumUl;
|
||||
paws_sm_func combiner_UlSpectrumAvailable;
|
||||
paws_sm_func combiner_UlSpectrumNotAvailable;
|
||||
paws_sm_func combiner_UlNotificationSuccess;
|
||||
//The following are all pure virtual
|
||||
paws_sm_func Send_AvailableSpectrumReq;
|
||||
paws_sm_func Send_Spectrum_Use_Notify;
|
||||
paws_sm_func Send_Spectrum_Use_Notify_New;
|
||||
void (*Send_Notifications)(void* sm_, paws_slave_info_t* slave_info);
|
||||
bool (*Process_Notify_Use_Resp)(void* sm_, json_value* resp);
|
||||
void (*update_slave_info)(void* sm_, paws_slave_info_t* slave_info);
|
||||
} paws_slave_sm_funcs_t;
|
||||
|
||||
typedef struct {
|
||||
int dummy1; // nothing
|
||||
} paws_slave_sm_data_t;
|
||||
|
||||
typedef struct {
|
||||
paws_sm_func Start;
|
||||
int (*run_tick)(void* sm_);
|
||||
} paws_slave_public_funcs_t;
|
||||
|
||||
typedef struct {
|
||||
paws_slave_sm_funcs_t* funcs; // THIS MUST BE FIRST.
|
||||
paws_slave_public_funcs_t* public_funcs;
|
||||
paws_slave_sm_data_t* data;
|
||||
} slave_sm_header_t;
|
||||
|
||||
typedef struct {
|
||||
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
|
||||
paws_sm_t* paws_sm;
|
||||
slave_sm_header_t slave_hdr;
|
||||
paws_sm_funcs_t local_paws_sm_funcs;
|
||||
paws_slave_sm_funcs_t local_slave_funcs;
|
||||
paws_slave_public_funcs_t local_public_funcs;
|
||||
paws_slave_sm_data_t slave_data_store;
|
||||
} paws_slave_sm_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
paws_slave_info_t slave_info;
|
||||
} paws_gop_private_data_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
void (*set_slaveInfo)(void* sm_, paws_slave_info_t* slave_info);
|
||||
paws_slave_info_t* (*get_slaveInfo)(void* sm_);
|
||||
} paws_gop_slave_sm_funcs_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
paws_gop_slave_sm_funcs_t* funcs;
|
||||
} gop_slave_sm_header_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
|
||||
paws_sm_t* paws_sm; //
|
||||
slave_sm_header_t slave_hdr; //
|
||||
paws_sm_funcs_t paws_sm_func_store; //
|
||||
paws_slave_sm_funcs_t slave_func_store; //
|
||||
paws_slave_public_funcs_t public_func_store; // down to here must match paws_slave_sm_t
|
||||
|
||||
gop_slave_sm_header_t gop_slave_hdr;
|
||||
paws_gop_private_data_t private_data_store;
|
||||
paws_gop_slave_sm_funcs_t gop_func_store; // these are functions specific to GOP
|
||||
|
||||
paws_slave_sm_t* slave_sm;
|
||||
} paws_gop_slave_sm_t;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
paws_device_info_t device_info;
|
||||
} paws_sop_private_data_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
void (*set_deviceInfo)(void* sm_, paws_device_info_t* device_info);
|
||||
paws_device_info_t* (*get_deviceInfo)(void* sm_);
|
||||
} paws_sop_slave_sm_funcs_t;
|
||||
|
||||
typedef struct {
|
||||
paws_sop_slave_sm_funcs_t* funcs;
|
||||
} sop_slave_sm_header_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
|
||||
paws_sm_t* paws_sm; //
|
||||
slave_sm_header_t slave_hdr; //
|
||||
paws_sm_funcs_t paws_sm_func_store; //
|
||||
paws_slave_sm_funcs_t slave_func_store; //
|
||||
paws_slave_public_funcs_t public_func_store; // down to here must match paws_slave_sm_t
|
||||
|
||||
sop_slave_sm_header_t sop_slave_hdr;
|
||||
paws_sop_private_data_t private_data_store;
|
||||
paws_sop_slave_sm_funcs_t sop_func_store; // these are functions specific to SOP
|
||||
|
||||
paws_slave_sm_t* slave_sm;
|
||||
} paws_sop_slave_sm_t;
|
||||
|
||||
|
||||
|
||||
#endif // #define PAWS_SLAVE_SM_TYPES_H_
|
||||
1350
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_sm.c
Normal file
1350
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_sm.c
Normal file
File diff suppressed because it is too large
Load Diff
19
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_sm.h
Normal file
19
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_sm.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_SM_H_
|
||||
#define PAWS_SM_H_
|
||||
|
||||
#include "paws_sm_types.h"
|
||||
|
||||
|
||||
|
||||
// funntions
|
||||
extern paws_sm_t* paws_sm_create(void* creator, paws_sm_funcs_t* child_funcs, const char* sm_name);
|
||||
extern void paws_sm_free(paws_sm_t** paws_sm);
|
||||
|
||||
#endif // #define PAWS_SM_H_
|
||||
|
||||
|
||||
209
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_sm_types.h
Normal file
209
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_sm_types.h
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_SM_TYPES_H_
|
||||
#define PAWS_SM_TYPES_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils/types.h"
|
||||
#include "json-parser/json.h"
|
||||
#include "gps/gps.h"
|
||||
#include "state-machine/state-machine.h"
|
||||
#include "timers/timer.h"
|
||||
#include "logger/logger.h"
|
||||
#include "logger/cloud_logger.h"
|
||||
|
||||
#include "paws_types.h"
|
||||
|
||||
|
||||
typedef void (*paws_sm_func)(void* sm_);
|
||||
typedef const char* (*IdToString)(void* sm_, int id);
|
||||
|
||||
#define PAWS_SM_FUNC_PROTO(fnc) static void fnc(void* sm_);
|
||||
|
||||
typedef struct {
|
||||
logger_cfg_t cfg;
|
||||
void* logger;
|
||||
} paws_sm_logger_t;
|
||||
|
||||
typedef struct {
|
||||
// defintion of all static class functions called from STL
|
||||
void (*store_state)(void* sm_, sm_state_info_t* sm_state_info);
|
||||
void (*free_state)(void* sm_, sm_state_info_t* sm_state_info);
|
||||
paws_sm_func read_state;
|
||||
void (*process_state_attributes)(void* sm_, sm_state_info_t* state_info);
|
||||
void (*process_state_timers)(void* sm_, char* timer_info);
|
||||
paws_sm_func Start;
|
||||
paws_sm_func Init_states;
|
||||
paws_sm_func Clear_Spectrums;
|
||||
paws_sm_func DLULSpectrumAvailable;
|
||||
paws_sm_func DLULSpectrumNotAvailable;
|
||||
paws_sm_func set_spectrum_InUse;
|
||||
paws_sm_func clear_spectrum_InUse;
|
||||
paws_sm_func check_spectrum_InUse;
|
||||
paws_sm_func ActivateSpectrumRuleset;
|
||||
paws_sm_func check_Notify_Required;
|
||||
paws_sm_func Start_Retry_Timer;
|
||||
paws_sm_func Stop_Retry_Timer;
|
||||
paws_sm_func Start_maxPolling_Timer;
|
||||
paws_sm_func Stop_maxPolling_Timer;
|
||||
paws_sm_func Start_maxPollingQuick_Timer;
|
||||
paws_sm_func Stop_maxPollingQuick_Timer;
|
||||
paws_sm_func Start_SpectrumPending_Timer;
|
||||
paws_sm_func Stop_SpectrumPending_Timer;
|
||||
paws_sm_func activatePendingSpectrum;
|
||||
paws_sm_func Start_SpectrumExpiry_Timer;
|
||||
paws_sm_func Stop_SpectrumExpiry_Timer;
|
||||
paws_sm_func combiner_selectDB;
|
||||
paws_sm_func combiner_DBerror;
|
||||
// defintion of static class functions which are not called directly by STL
|
||||
bool (*Check_HTTP_Result)(void* sm_, json_value* resp, bool raise);
|
||||
void (*combiner_ProcessDbUpdate)(void* sm_, json_value* new_db_spec);
|
||||
void (*set_db)(void* sm_, paws_db_item_t* db);
|
||||
bool (*Check_Valid_Resp)(void* sm_, json_value* resp, bool raise);
|
||||
void (*Process_Available_Spectrum_Resp)(void* sm_, json_value* resp, lte_direction_e dir, time_t resp_time);
|
||||
avail_spectrum_t* (*GetAvailSpectrumResp)(void* sm_);
|
||||
void (*checkAvailableSpectrum)(void* sm_);
|
||||
bool (*set_selected_spectrum)(void* sm_, spec_cfg_t* spec_cfg);
|
||||
spec_cfg_t* (*get_spectrum_InUse)(void* sm_);
|
||||
void (*clear_Ruleset)(void* sm_);
|
||||
float (*get_max_location_change)(void* sm_);
|
||||
uint32_t (*get_max_polling_secs)(void* sm_);
|
||||
void (*Process_Notify_Use_Resp)(void* sm_, json_value* resp);
|
||||
void (*timeout_handler)(void* sm_, uint32_t id);
|
||||
void (*Retry_Timer_Hdlr)(void* sm_);
|
||||
void (*set_maxPollingQuick)(void* sm_, uint32_t dur_secs);
|
||||
void (*maxPolling_Timer_Hdlr)(void* sm_);
|
||||
void (*maxPollingQuick_Timer_Hdlr)(void* sm_);
|
||||
void (*SpectrumPending_Timer_Hdlr)(void* sm_);
|
||||
void (*SpectrumExpiry_Timer_Hdlr)(void* sm_);
|
||||
void (*set_master_info)(void* sm_, paws_device_info_t* master_info);
|
||||
void (*set_defaultInfo)(void* sm_, float max_location_change, uint32_t max_polling_secs);
|
||||
void (*set_gps)(void* sm_, paws_gps_location_t* gps);
|
||||
void (*gps_changed)(void* sm_);
|
||||
const char* (*state_id_2_str)(void* sm_, int id);
|
||||
const char* (*event_id_2_str)(void* sm_, int id);
|
||||
void (*state_changed_dbg)(void* sm_, int old_state, int new_state);
|
||||
void (*event_processed_dbg)(void* sm_, int event_id);
|
||||
bool (*set_LogInfo)(void* sm_, paws_sm_logger_t* logger, logger_cfg_t* cfg);
|
||||
bool (*set_msgLogInfo)(void* sm_, logger_cfg_t* cfg);
|
||||
void (*app_log)(void* sm_, const char* file_, int line_, const char* func_, const char* logline, log_level_e level);
|
||||
void (*app_log_tvwsdb_msg)(void* sm_, const char* msg);
|
||||
void (*msg_log_tvwsdb_msg)(void* sm_, char* cloud_log_j);
|
||||
void (*raise_)(void* sm_, int event_id);
|
||||
bool (*Init)(void* sm_, float min_dbm_100k, uint16_t db_retry_secs, uint32_t max_polling_quick_secs);
|
||||
paws_sm_func process_next_timer_tick;
|
||||
int (*process_events)(void* sm_);
|
||||
bool (*stl_init)(void* sm_, State *state_transition_table, int initial_state, bool run_pre);
|
||||
void (*stl_set_state_explicit)(void* sm_, int state);
|
||||
} paws_sm_funcs_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
paws_db_item_t selected_db;
|
||||
uint8_t db_ok;
|
||||
paws_gps_location_t gps;
|
||||
|
||||
// log info
|
||||
paws_sm_logger_t msg_log;
|
||||
|
||||
// paws settings
|
||||
float min_dbm_100k; // min dbm per 100k to qualify for selection
|
||||
uint16_t db_retry_secs; // how often to retry events (default=15)
|
||||
|
||||
// ruleset
|
||||
float default_max_location_change;
|
||||
float specific_max_location_change;
|
||||
uint32_t default_max_polling_secs;
|
||||
uint32_t specific_max_polling_secs;
|
||||
uint32_t max_polling_quick_secs;
|
||||
|
||||
|
||||
avail_spectrum_t* avail_spectrum_resp; // PAWS SPECTRUM-AVAIL-RESP
|
||||
spec_cfg_t* available_spectrum; // available, but might not have a corresponding paired spec.
|
||||
spec_cfg_t* pending_spectrum; // resp has a spectrum, but start_time is in future.
|
||||
spec_cfg_t* selected_spectrum; // selected to be used
|
||||
spec_cfg_t* spectrum_in_use; // selected actually being used
|
||||
|
||||
paws_device_info_t master_info;
|
||||
} paws_sm_data_t;
|
||||
|
||||
typedef struct {
|
||||
StateMachine* stl;
|
||||
TimerManager* timer_manager;
|
||||
} paws_sm_stl_data_t;
|
||||
|
||||
typedef struct {
|
||||
device_name_t unique_id;
|
||||
void* creator; // state machine which has created this entity
|
||||
paws_sm_funcs_t* funcs; // THIS MUST BE FIRST.
|
||||
paws_sm_data_t* data;
|
||||
paws_sm_stl_data_t* stl_data;
|
||||
} paws_sm_header_t;
|
||||
|
||||
typedef struct {
|
||||
paws_sm_header_t paws_sm_hdr; // THIS MUST BE FIRST IN ANY SM WHICH HAS A PAWS_SM.
|
||||
paws_sm_data_t paws_sm_data_store;
|
||||
paws_sm_stl_data_t paws_sm_stl_data_store;
|
||||
|
||||
paws_sm_funcs_t local_funcs;
|
||||
} paws_sm_t;
|
||||
|
||||
|
||||
|
||||
#define FOREACH_EV(EV) \
|
||||
EV(LocalDB_Error) \
|
||||
EV(Start) \
|
||||
EV(GPS_location_changed) \
|
||||
EV(DB_UpdateTriggered) \
|
||||
EV(DB_Error) \
|
||||
EV(DB_Updated) \
|
||||
EV(DB_Found) \
|
||||
EV(DB_NotFound) \
|
||||
EV(DB_Response_Failure) \
|
||||
EV(Available_Spectrum_Resp) \
|
||||
EV(SpectrumAvailable) \
|
||||
EV(SpectrumNotAvailable) \
|
||||
EV(SpectrumPending) \
|
||||
EV(DlUlSpectrumAvailable) \
|
||||
EV(DlUlSpectrumNotAvailable) \
|
||||
EV(SpectrumActive) \
|
||||
EV(SpectrumNotActive) \
|
||||
EV(Notification_Required) \
|
||||
EV(Notification_Not_Required) \
|
||||
EV(Notification_Success) \
|
||||
EV(Notification_Failure) \
|
||||
EV(Retry_Timeout) \
|
||||
EV(maxPolling_Timeout) \
|
||||
EV(maxPollingQuick_Timeout) \
|
||||
EV(SpectrumPending_Timeout) \
|
||||
EV(SpectrumExpiry_Timeout) \
|
||||
EV(PAWS_SM_END_EV_MARKER)
|
||||
|
||||
#define GEN_EV_ENUM(ENUM) ev_##ENUM,
|
||||
|
||||
enum paws_event_e {
|
||||
ev_Dummy = SM_EVENT_START_OF_USER_IDS,
|
||||
FOREACH_EV(GEN_EV_ENUM)
|
||||
};
|
||||
|
||||
|
||||
typedef enum {
|
||||
RETRY_TIMER_ID = 1,
|
||||
SPECTRUM_EXPIRY_TIMER_ID,
|
||||
SPECTRUM_PENDING_TIMER_ID,
|
||||
MAX_POLLING_TIMER_ID,
|
||||
MAX_POLLING_QUICK_TIMER_ID,
|
||||
|
||||
PAWS_SM_TIMER_END
|
||||
} paws_sm_timers_e;
|
||||
|
||||
|
||||
#endif // #define PAWS_SM_TYPES_H_
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_TIMER_INFO_H_
|
||||
#define PAWS_TIMER_INFO_H_
|
||||
|
||||
//####### Timer tolerance
|
||||
// some timers experiencing max duration between actions. These tolerances specify how close to the end of max-duration to reach before expiring the timer
|
||||
#define DB_DISCOVERY_TIMER_TOLERANCE (60)
|
||||
#define SPECTRUM_EXPIRY_TIMER_TOLERANCE (15)
|
||||
#define MAX_POLLING_TIMER_TOLERANCE (15)
|
||||
|
||||
// ####### Timer durations
|
||||
#define DB_SETTINGS_INITIAL_DURATION (1 * 60) // start off every 1 mins, but this will get overwritten
|
||||
#define DB_DEVICES_INITIAL_DURATION (1 * 60) // start off every 1 mins, but this will get overwritten
|
||||
#define PERIODIC_GPS_DEVICES_INITIAL_DURATION (5) // quick check until we have SETIINGS defined
|
||||
#define DB_DISCOVERY_TIMER_INITIAL_DURATION (DB_DISCOVERY_TIMER_TOLERANCE + 60) // start off every 1 min, but this will get overwritten by the received refreshRate.
|
||||
#define DB_DISCOVERY_TIMER_QUICK_DURATION (75 * 60) // ## 75 minutes ## as per ETSI EN 301 598 v1.1.1
|
||||
#define LOCAL_ISSUE_BACKOFF_TIMER_DURATION (10) // There has been a local problem. How long to wait before we re-init the whole system
|
||||
|
||||
#endif // #define PAWS_TIMER_INFO_H_
|
||||
|
||||
74
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_types.c
Normal file
74
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_types.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
|
||||
#include "paws_types.h"
|
||||
#include "paws_dal_types.h"
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
|
||||
// Return code as it per strcmp
|
||||
// p1 < p2: return -1
|
||||
// p1 == p2: return 0
|
||||
// p1 > p2: return +2
|
||||
int ul_dl_spec_cfg_freq_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2)
|
||||
{
|
||||
if ((!p1) || (!p1->dl_cfg) || (!p1->ul_cfg) || (!p2) || (!p2->dl_cfg) || (!p2->ul_cfg))
|
||||
return -1;
|
||||
|
||||
// frequency
|
||||
// dl
|
||||
int ret = (p1->dl_cfg->start_hz < p2->dl_cfg->start_hz) ? -1 : ((p1->dl_cfg->start_hz == p2->dl_cfg->start_hz) ? 0 : 1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
// ul
|
||||
ret = (p1->ul_cfg->start_hz < p2->ul_cfg->start_hz) ? -1 : ((p1->ul_cfg->start_hz == p2->ul_cfg->start_hz) ? 0 : 1);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Return code as it per strcmp
|
||||
// p1 < p2: return -1
|
||||
// p1 == p2: return 0
|
||||
// p1 > p2: return +2
|
||||
// Note that bandwidth is checked first, then power.
|
||||
int ul_dl_spec_cfg_pwr_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2)
|
||||
{
|
||||
if ((!p1) || (!p1->dl_cfg) || (!p1->ul_cfg) || (!p2) || (!p2->dl_cfg) || (!p2->ul_cfg))
|
||||
return -1;
|
||||
|
||||
// bandwidth
|
||||
// dl
|
||||
int ret = (p1->dl_cfg->bandwidth < p2->dl_cfg->bandwidth) ? -1 : ((p1->dl_cfg->bandwidth == p2->dl_cfg->bandwidth) ? 0 : 1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
// ul
|
||||
ret = (p1->ul_cfg->bandwidth < p2->ul_cfg->bandwidth) ? -1 : ((p1->ul_cfg->bandwidth == p2->ul_cfg->bandwidth) ? 0 : 1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
|
||||
// power
|
||||
// dl
|
||||
ret = (p1->dl_cfg->dbm < p2->dl_cfg->dbm) ? -1 : ((p1->dl_cfg->dbm == p2->dl_cfg->dbm) ? 0 : 1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
// ul
|
||||
ret = (p1->ul_cfg->dbm < p2->ul_cfg->dbm) ? -1 : ((p1->ul_cfg->dbm == p2->ul_cfg->dbm) ? 0 : 1);
|
||||
return ret;
|
||||
|
||||
}
|
||||
24
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_types.h
Normal file
24
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_types.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_TYPES_
|
||||
#define PAWS_TYPES_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "utils/types.h"
|
||||
#include "paws_dal_devices.h"
|
||||
#include "paws_dal_settings.h"
|
||||
#include "paws_dal_state.h"
|
||||
#include "paws_dal_database.h"
|
||||
|
||||
|
||||
int ul_dl_spec_cfg_freq_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2);
|
||||
int ul_dl_spec_cfg_pwr_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2);
|
||||
|
||||
extern int ul_dl_spec_cfg_compare(ul_dl_spec_cfg_t* p1, ul_dl_spec_cfg_t* p2);
|
||||
|
||||
#endif // PAWS_TYPES_
|
||||
|
||||
565
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_utils.c
Executable file
565
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_utils.c
Executable file
@@ -0,0 +1,565 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "json-parser/json_utils.h"
|
||||
|
||||
#include "paws_utils.h"
|
||||
|
||||
#include "paws_globals.h"
|
||||
#include "paws_types.h"
|
||||
#include "paws_dal_types.h"
|
||||
#include "lte_utils.h"
|
||||
|
||||
|
||||
|
||||
char logline_[LOGGER_MAX_LENGTH];
|
||||
|
||||
#define DBM_NO_POWER (-999)
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void set_stop_time(time_t* stop_time_t, time_t now_, uint32_t maxPollingSecs)
|
||||
{
|
||||
time_t forced_stop_t = now_ + maxPollingSecs;
|
||||
if (g_paws_reg_domain == PAWS_REGDOMAIN_ETSI)
|
||||
{
|
||||
if (*stop_time_t > forced_stop_t) // ETSI 301 598 4.2.6.3.2
|
||||
{
|
||||
*stop_time_t = forced_stop_t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void weblist_free(paws_weblist_t** weblist)
|
||||
{
|
||||
if ((weblist) && (*weblist))
|
||||
{
|
||||
if ((*weblist)->items)
|
||||
{
|
||||
free_and_null((void*)&(*weblist)->items);
|
||||
}
|
||||
free_and_null((void**)weblist);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
paws_weblist_t* json_2_weblist(json_value* src)
|
||||
{
|
||||
paws_weblist_t* weblist = NULL;
|
||||
|
||||
// check src
|
||||
if (!src)
|
||||
goto error_hdl;
|
||||
|
||||
// malloc a new type
|
||||
if (!(weblist = malloc(sizeof(paws_weblist_t))))
|
||||
goto error_hdl;
|
||||
memset(weblist, 0, (sizeof(paws_weblist_t)));
|
||||
|
||||
// get refresh rate
|
||||
char* s = NULL;
|
||||
weblist->refresh_rate = ((s = json_get_string(src, "ws_databases/refresh_rate"))) ? atoi(s) : 0;
|
||||
|
||||
// now fill in the rest
|
||||
json_value* v = json_get(src, "ws_databases/db");
|
||||
if (v && v->type == json_array)
|
||||
{
|
||||
weblist->num_items = v->u.array.length;
|
||||
if (weblist->num_items)
|
||||
{
|
||||
if (!(weblist->items = malloc((sizeof(weblist_item_t) * weblist->num_items))))
|
||||
goto error_hdl;
|
||||
memset(weblist->items, 0, (sizeof(weblist_item_t) * weblist->num_items));
|
||||
|
||||
weblist_item_t* item = NULL;
|
||||
for (int i=0; i<weblist->num_items; i++)
|
||||
{
|
||||
char *ss = NULL;
|
||||
int slen;
|
||||
json_value* d = v->u.array.values[i];
|
||||
item = &(weblist->items[i]);
|
||||
if ((!d) || (d->type!=json_object))
|
||||
goto error_hdl;
|
||||
|
||||
// url
|
||||
if (!(ss = json_get_string(d, "url")))
|
||||
goto error_hdl;
|
||||
slen = snprintf(item->url, MAX_URL_LENGTH, "%s", ss);
|
||||
if ((slen < 0) || (slen >= MAX_URL_LENGTH))
|
||||
goto error_hdl;
|
||||
|
||||
// db_provider_name
|
||||
if (!(ss = json_get_string(d, "db_provider_name")))
|
||||
goto error_hdl;
|
||||
slen = snprintf(item->name, MAX_DB_NAME_LENGTH, "%s", ss);
|
||||
if ((slen < 0) || (slen >= MAX_DB_NAME_LENGTH))
|
||||
goto error_hdl;
|
||||
|
||||
// mcwsd_support
|
||||
if (!(json_get_bool(d, "MCWSD_support", &item->mcwsd_support)))
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return weblist;
|
||||
|
||||
error_hdl:
|
||||
if (weblist) weblist_free(&weblist);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
// convert timestamp to time_t
|
||||
// returns -1 on failure
|
||||
int timestamp_to_timet(char* src)
|
||||
{
|
||||
struct tm tm;
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
|
||||
if (!src)
|
||||
return -1;
|
||||
|
||||
// remove micosecs
|
||||
char *pos = strrchr(src, '.');
|
||||
if (pos)
|
||||
*pos = '\0';
|
||||
|
||||
// convert to tm
|
||||
if (!(strptime(src, "%Y-%m-%dT%H:%M:%S", &tm)))
|
||||
return -1;
|
||||
else
|
||||
return (mktime(&tm));
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
avail_spectrum_t* json_resp_2_avail_spectrum(void *sm_, json_value* src, lte_direction_e dir, uint8_t lte_band_id, time_t resp_time, float min_dbm_100k)
|
||||
{
|
||||
uint32_t i, j, k, m, n;
|
||||
uint32_t band_start_hz, band_end_hz;
|
||||
int32_t band_spacing;
|
||||
char *timestamp_str;
|
||||
avail_spectrum_t* avail_spec = NULL;
|
||||
spectrum_spec_t* spectrum_spec = NULL;
|
||||
spectrum_schedule_t* spectrum_sched = NULL;
|
||||
spec_profile_type_t* profile = NULL;
|
||||
int contiguous;
|
||||
|
||||
if (!(get_lte_band_channel(lte_band_id, dir, &band_start_hz, &band_end_hz, &band_spacing)))
|
||||
return NULL;
|
||||
|
||||
// calulate the wsdb time phase using the timesdtamp in the message and our local response time
|
||||
// get the timestamp
|
||||
if (!(timestamp_str = json_get_string(src, "result/timestamp")))
|
||||
goto error_hdl;
|
||||
// store timestamp as time_t
|
||||
time_t db_timestamp, db_phase;
|
||||
if ((db_timestamp = timestamp_to_timet(timestamp_str)) == -1)
|
||||
goto error_hdl;
|
||||
db_phase = db_timestamp - resp_time;
|
||||
|
||||
// malloc the main struct
|
||||
if (!(avail_spec = avail_spectrum_new()))
|
||||
goto error_hdl;
|
||||
spectrum_spec_t* tail_spectrum_spec = NULL;
|
||||
|
||||
json_value* spectrum_specs_j=NULL;
|
||||
if (!(spectrum_specs_j = json_get(src, "result/spectrumSpecs")))
|
||||
goto error_hdl;
|
||||
|
||||
if (spectrum_specs_j->type != json_array)
|
||||
goto error_hdl;
|
||||
|
||||
// for each spectrum spec
|
||||
for (i = 0; i < spectrum_specs_j->u.array.length; i++)
|
||||
{
|
||||
if (!(spectrum_spec = spectrum_spec_new()))
|
||||
goto error_hdl;
|
||||
|
||||
spectrum_schedule_t* tail_spectrum_sched = NULL;
|
||||
|
||||
json_value* spectrum_spec_j = spectrum_specs_j->u.array.values[i];
|
||||
if (spectrum_spec_j->type != json_object)
|
||||
goto error_hdl;
|
||||
|
||||
json_value* spectra_schedules_j = NULL;
|
||||
if (!(spectra_schedules_j = json_get(spectrum_spec_j, "spectrumSchedules")))
|
||||
continue;
|
||||
if (spectra_schedules_j->type != json_array)
|
||||
goto error_hdl;
|
||||
|
||||
// ruleset info
|
||||
// we get this first because, for ETSI regulation domain, we limit the expiry time to the time of the tUpdate (max_polling_secs)
|
||||
json_value* ruleset_j = NULL;
|
||||
int64_t maxPollingSecs;
|
||||
double maxLocationChange;
|
||||
if (!(((ruleset_j = json_get(spectrum_spec_j, "rulesetInfo"))) &&
|
||||
((json_get_int(ruleset_j, "maxPollingSecs", &maxPollingSecs))) &&
|
||||
((json_get_double(ruleset_j, "maxLocationChange", (double*)&maxLocationChange)))))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
spectrum_spec->ruleset_info.maxPollingSecs = maxPollingSecs;
|
||||
spectrum_spec->ruleset_info.maxLocationChange = (float)maxLocationChange;
|
||||
|
||||
spectrum_spec->max_contiguous_bw_hz_within_band = 0;
|
||||
|
||||
for (j = 0; j < spectra_schedules_j->u.array.length; j++)
|
||||
{
|
||||
json_value* spectrum_sched_j = spectra_schedules_j->u.array.values[i];
|
||||
if (spectrum_sched_j->type != json_object)
|
||||
goto error_hdl;
|
||||
|
||||
// get times and check if this spectrum has already expired
|
||||
// get an event time if present
|
||||
json_value* event_time_range_j = NULL;
|
||||
char* start_time = NULL;
|
||||
char* stop_time = NULL;
|
||||
if (!(((event_time_range_j = json_get(spectrum_sched_j, "eventTime"))) &&
|
||||
((start_time = json_get_string(event_time_range_j, "startTime"))) &&
|
||||
((stop_time = json_get_string(event_time_range_j, "stopTime")))))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
// store times as time_t
|
||||
time_t start_time_t, stop_time_t;
|
||||
if ((start_time_t = timestamp_to_timet(start_time)) == -1)
|
||||
goto error_hdl;
|
||||
start_time_t -= db_phase;
|
||||
if ((stop_time_t = timestamp_to_timet(stop_time)) == -1)
|
||||
goto error_hdl;
|
||||
stop_time_t -= db_phase;
|
||||
|
||||
time_t now_ = time(NULL);
|
||||
|
||||
// limit start/stop times if regulation body forces it
|
||||
set_stop_time(&stop_time_t, now_, spectrum_spec->ruleset_info.maxPollingSecs);
|
||||
|
||||
// if start time > stop_time it is invalid. This could happen if domain has limited stop time
|
||||
if (start_time_t > stop_time_t)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// if start_time is in the past, set it to 'now'
|
||||
if (now_ > start_time_t)
|
||||
start_time_t = now_;
|
||||
|
||||
// if stop time is already expired, drop this spectrum_sched
|
||||
if (now_ > stop_time_t)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!(spectrum_sched = spectrum_sched_new()))
|
||||
goto error_hdl;
|
||||
|
||||
spec_profile_type_t* tail_profile = NULL;
|
||||
|
||||
// populate the times
|
||||
spectrum_sched->event_time_range.start_time = start_time_t;
|
||||
spectrum_sched->event_time_range.stop_time = stop_time_t;
|
||||
|
||||
json_value* spectra_j = NULL;
|
||||
if (!(spectra_j = json_get(spectrum_sched_j, "spectra")))
|
||||
continue;
|
||||
if (spectra_j->type != json_array)
|
||||
goto error_hdl;
|
||||
|
||||
// for each spectra item
|
||||
for (k = 0; k < spectra_j->u.array.length; k++)
|
||||
{
|
||||
json_value* spectra_item_j = spectra_j->u.array.values[k];
|
||||
if (spectra_item_j->type != json_object)
|
||||
goto error_hdl;
|
||||
|
||||
// is this for resolutionBwHx = 100000.0
|
||||
double res_bw_hz;
|
||||
if (!(json_get_double(spectra_item_j, "resolutionBwHz", &res_bw_hz)))
|
||||
continue;
|
||||
if (res_bw_hz != (double)100000)
|
||||
continue;
|
||||
|
||||
json_value* profiles_j = NULL;
|
||||
if (!(profiles_j = json_get(spectra_item_j, "profiles")))
|
||||
continue;
|
||||
if (profiles_j->type != json_array)
|
||||
goto error_hdl;
|
||||
|
||||
contiguous = 0;
|
||||
|
||||
for (m = 0; m < profiles_j->u.array.length; m++)
|
||||
{
|
||||
json_value* profile_j = profiles_j->u.array.values[m];
|
||||
if (profile_j->type != json_array)
|
||||
goto error_hdl;
|
||||
|
||||
// check there are "pairs" of assignments provided
|
||||
if (profile_j->u.array.length % 2)
|
||||
goto error_hdl;
|
||||
|
||||
for (n = 0; n < (profile_j->u.array.length / 2); n++)
|
||||
{
|
||||
double start_hz_dbl, end_hz_dbl, dbm;
|
||||
uint32_t start_hz, end_hz;
|
||||
|
||||
json_value* item_j = profile_j->u.array.values[n*2];
|
||||
if (!(json_get_double(item_j, "hz", &start_hz_dbl)))
|
||||
goto error_hdl;
|
||||
if (!(json_get_double(item_j, "dbm", &dbm)))
|
||||
goto error_hdl;
|
||||
|
||||
item_j = profile_j->u.array.values[(n*2)+1];
|
||||
if (!(json_get_double(item_j, "hz", &end_hz_dbl)))
|
||||
goto error_hdl;
|
||||
|
||||
start_hz = (uint32_t)start_hz_dbl;
|
||||
end_hz = (uint32_t)end_hz_dbl;
|
||||
|
||||
// it is within the band range
|
||||
if ((end_hz <= band_start_hz) || (start_hz >= band_end_hz))
|
||||
{
|
||||
// update contiguous
|
||||
if (contiguous > spectrum_spec->max_contiguous_bw_hz_within_band)
|
||||
spectrum_spec->max_contiguous_bw_hz_within_band = contiguous;
|
||||
contiguous = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// does it have ANY power
|
||||
if (DBM_NO_POWER == dbm)
|
||||
{
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "Channel has no power : %.2fMhz->%.2fMhz", start_hz_dbl / 1000000, end_hz_dbl / 1000000);
|
||||
// update contiguous
|
||||
if (contiguous > spectrum_spec->max_contiguous_bw_hz_within_band)
|
||||
spectrum_spec->max_contiguous_bw_hz_within_band = contiguous;
|
||||
contiguous = 0;
|
||||
continue;
|
||||
}
|
||||
// does it have ENOUGH power
|
||||
if (dbm < min_dbm_100k)
|
||||
{
|
||||
LOG_PRINT(sm_, LOG_NOTICE, "Channel has < min (%.2fdBm) power : %.2fMhz->%.2fMhz pwr:%.2fdBm", min_dbm_100k, start_hz_dbl/1000000, end_hz_dbl/1000000, dbm);
|
||||
// update contiguous
|
||||
if (contiguous > spectrum_spec->max_contiguous_bw_hz_within_band)
|
||||
spectrum_spec->max_contiguous_bw_hz_within_band = contiguous;
|
||||
contiguous = 0;
|
||||
continue;
|
||||
}
|
||||
// add to contiguous
|
||||
uint32_t prof_bw = end_hz - start_hz;
|
||||
if (start_hz < band_start_hz)
|
||||
prof_bw -= (band_start_hz - start_hz);
|
||||
else if (band_end_hz < end_hz)
|
||||
prof_bw -= (end_hz - band_end_hz);
|
||||
|
||||
contiguous += prof_bw;
|
||||
|
||||
// malloc an entry
|
||||
profile = malloc(sizeof(spec_profile_type_t));
|
||||
memset(profile, 0, sizeof(spec_profile_type_t));
|
||||
profile->start_hz = start_hz;
|
||||
profile->end_hz = end_hz;
|
||||
profile->dbm = (float)dbm;
|
||||
|
||||
// append to spectrum_schedule->profiles
|
||||
if (spectrum_sched->profiles == NULL)
|
||||
{
|
||||
spectrum_sched->profiles = profile;
|
||||
tail_profile = profile;
|
||||
}
|
||||
else
|
||||
{
|
||||
tail_profile->next = profile;
|
||||
tail_profile = profile;
|
||||
}
|
||||
profile = NULL;
|
||||
}
|
||||
} // profiles_j
|
||||
} // spectra
|
||||
|
||||
// check if something was added for this spectrum_schedule
|
||||
if (spectrum_sched->profiles == NULL)
|
||||
spectrum_sched_free(&spectrum_sched);
|
||||
else
|
||||
{
|
||||
// append to spectrum_spec->spectrum_schedules
|
||||
if (spectrum_spec->spectrum_schedules == NULL)
|
||||
{
|
||||
spectrum_spec->spectrum_schedules = spectrum_sched;
|
||||
tail_spectrum_sched = spectrum_sched;
|
||||
}
|
||||
else
|
||||
{
|
||||
tail_spectrum_sched->next = spectrum_sched;
|
||||
tail_spectrum_sched = spectrum_sched;
|
||||
}
|
||||
spectrum_sched = NULL;
|
||||
}
|
||||
} // spectra_schedules_j
|
||||
|
||||
// update contiguous
|
||||
if (contiguous > spectrum_spec->max_contiguous_bw_hz_within_band)
|
||||
{
|
||||
spectrum_spec->max_contiguous_bw_hz_within_band = contiguous;
|
||||
}
|
||||
|
||||
// check if something was added for this spectrum_spec
|
||||
if (spectrum_spec->spectrum_schedules == NULL)
|
||||
spectrum_spec_free(&spectrum_spec);
|
||||
else
|
||||
{
|
||||
// max contiguous bw hz
|
||||
double max_contiguous_bw_hz;
|
||||
if ((json_get_double(spectrum_spec_j, "maxContiguousBwHz", &max_contiguous_bw_hz)))
|
||||
spectrum_spec->max_contiguous_bw_hz = (float)max_contiguous_bw_hz;
|
||||
|
||||
// need spectrum report
|
||||
if (!(json_get_bool(spectrum_spec_j, "needsSpectrumReport", &spectrum_spec->needsSpectrumReport)))
|
||||
spectrum_spec->needsSpectrumReport = false;
|
||||
|
||||
// append to avail_spectrum->spectrum_specs
|
||||
if (avail_spec->spectrum_specs == NULL)
|
||||
{
|
||||
avail_spec->spectrum_specs = spectrum_spec;
|
||||
}
|
||||
else
|
||||
{
|
||||
tail_spectrum_spec->next = spectrum_spec;
|
||||
}
|
||||
tail_spectrum_spec = spectrum_spec;
|
||||
spectrum_spec = NULL;
|
||||
}
|
||||
|
||||
} // spectrum_specs
|
||||
|
||||
return avail_spec;
|
||||
|
||||
error_hdl:
|
||||
if (profile) free(profile);
|
||||
if (spectrum_spec) spectrum_spec_free(&spectrum_spec);
|
||||
if (spectrum_sched) spectrum_sched_free(&spectrum_sched);
|
||||
if (avail_spec) avail_spectrum_free(&avail_spec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static void spectrum_sched_print(spectrum_schedule_t* sched, int spec_id, int sched_id)
|
||||
{
|
||||
char tmptime1[50];
|
||||
char tmptime2[50];
|
||||
strftime(tmptime1, sizeof(tmptime1), "%Y-%m-%dT%H:%M:%S", gmtime(&sched->event_time_range.start_time));
|
||||
strftime(tmptime2, sizeof(tmptime2), "%Y-%m-%dT%H:%M:%S", gmtime(&sched->event_time_range.stop_time));
|
||||
printf("[spec %d][sched %d] start=%s stop=%s \n", spec_id, sched_id, tmptime1, tmptime2);
|
||||
|
||||
spec_profile_type_t* prof = sched->profiles;
|
||||
if (prof == NULL)
|
||||
printf("[spec %d][sched %d] profiles=%p\n", spec_id, sched_id, prof);
|
||||
while (prof)
|
||||
{
|
||||
printf("[spec %d][sched %d] prof: start:%d end:%d dbm:%.2f \n", spec_id, sched_id, prof->start_hz, prof->end_hz, prof->dbm );
|
||||
prof = prof->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void spectrum_spec_print(spectrum_spec_t* spec, int spec_id)
|
||||
{
|
||||
int sched_id = 0;
|
||||
|
||||
printf("[spec %d] max_contiguous_bw_hz=%.4f \n", spec_id, spec->max_contiguous_bw_hz);
|
||||
printf("[spec %d] max_contiguous_bw_hz_within_band=%.4f \n", spec_id, spec->max_contiguous_bw_hz_within_band);
|
||||
printf("[spec %d] needsSpectrumReport=%d \n", spec_id, spec->needsSpectrumReport);
|
||||
printf("[spec %d] ruleSetInfo [ maxPollingSecs=%d maxLocationChange=%.2f ] \n", spec_id, spec->ruleset_info.maxPollingSecs, spec->ruleset_info.maxLocationChange);
|
||||
|
||||
spectrum_schedule_t* spectrum_sched = spec->spectrum_schedules;
|
||||
if (spectrum_sched == NULL)
|
||||
printf(" spectrum_schedules = %p \n", spectrum_sched);
|
||||
while (spectrum_sched)
|
||||
{
|
||||
spectrum_sched_print(spectrum_sched, spec_id, sched_id);
|
||||
spectrum_sched = spectrum_sched->next;
|
||||
sched_id += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void avail_spectrum_print(avail_spectrum_t* s)
|
||||
{
|
||||
int spec_id = 0;
|
||||
|
||||
printf("avail_spectrum=%p \n", s);
|
||||
if (s)
|
||||
{
|
||||
spectrum_spec_t* spectrum_spec = s->spectrum_specs;
|
||||
if (spectrum_spec == NULL)
|
||||
printf(" spectrum_specs = %p \n", spectrum_spec);
|
||||
while (spectrum_spec)
|
||||
{
|
||||
spectrum_spec_print(spectrum_spec, spec_id);
|
||||
spectrum_spec = spectrum_spec->next;
|
||||
spec_id += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool json_dbUpdate_2_dblist(json_value* dbUpdate_j, const char* token, uint32_t* num_db, paws_db_item_t* db_list)
|
||||
{
|
||||
if (!((dbUpdate_j) && (token) && (db_list)))
|
||||
return false;
|
||||
|
||||
if (dbUpdate_j->type != json_array)
|
||||
return false;
|
||||
|
||||
// clean the old DB
|
||||
memset(db_list, 0, (sizeof(paws_db_item_t) * PAWS_MAX_DB_LIST));
|
||||
*num_db = 0;
|
||||
|
||||
for (uint32_t i = 0; i < dbUpdate_j->u.array.length; i++)
|
||||
{
|
||||
json_value* db_j = dbUpdate_j->u.array.values[i];
|
||||
char *name = NULL;
|
||||
char *uri = NULL;
|
||||
if (!(((db_j->type == json_object)) &&
|
||||
((name = json_get_string(db_j, "name"))) &&
|
||||
((uri = json_get_string(db_j, "uri")))))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// add to db_info
|
||||
memcpy(&(db_list[i].db_url.token[0]), token, strlen(token));
|
||||
memcpy(&(db_list[i].db_url.host[0]), uri, strlen(uri));
|
||||
memcpy(&(db_list[i].name[0]), name, strlen(name));
|
||||
db_list[i].valid = true;
|
||||
|
||||
(*num_db)++;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
memset(db_list, 0, (sizeof(paws_db_item_t) * PAWS_MAX_DB_LIST));
|
||||
*num_db = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
46
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_utils.h
Executable file
46
software/pawsc/paws/SpectrumDBClient/apps/paws/paws_utils.h
Executable file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PAWS_UTILS_H_
|
||||
#define PAWS_UTILS_H_
|
||||
|
||||
#include "json-parser/json.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
#include "paws_types.h"
|
||||
#include "paws_globals.h"
|
||||
#include "paws_common.h"
|
||||
|
||||
extern void weblist_free(paws_weblist_t** weblist);
|
||||
extern paws_weblist_t* json_2_weblist(json_value* src);
|
||||
|
||||
extern avail_spectrum_t* json_resp_2_avail_spectrum(void *sm_, json_value* src, lte_direction_e dir, uint8_t lte_band_id, time_t resp_time, float min_dbm_100k);
|
||||
extern void avail_spectrum_print(avail_spectrum_t* spec);
|
||||
|
||||
extern int timestamp_to_timet(char* src);
|
||||
|
||||
extern bool json_dbUpdate_2_dblist(json_value* dbUpdate_j, const char* token, uint32_t* num_db, paws_db_item_t* db_list);
|
||||
|
||||
|
||||
extern char logline_[];
|
||||
#define LOG_PRINT(sm, loglevel, fmt, args...) { \
|
||||
if (loglevel >= gPawsAppLoggerCfg.level) \
|
||||
{ \
|
||||
int slen = snprintf(logline_, LOGGER_MAX_LENGTH, fmt, ##args); \
|
||||
if (!((slen <= 0) || (slen >= LOGGER_MAX_LENGTH))) \
|
||||
{ \
|
||||
LOCAL_FUNC(sm, app_log)(sm, __FILENAME__, __LINE__, __func__, logline_, loglevel); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define APPLOG_TVWSDB_MSG(sm, msg) { LOCAL_FUNC(sm, app_log_tvwsdb_msg)(sm, msg); }
|
||||
#define MSGLOG_TVWSDB_MSG(sm, jmsg) { LOCAL_FUNC(sm, msg_log_tvwsdb_msg)(sm, jmsg); }
|
||||
|
||||
#define FUNC_DBG(sm) LOG_PRINT(sm, LOG_FUNC, " ")
|
||||
|
||||
|
||||
#endif // #define PAWS_UTILS_H_
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include "sctp_agent_db_info.h"
|
||||
|
||||
#define MAX_SCTP_AGENT_DB_NAME (100)
|
||||
static char g_sctp_agent_db[MAX_SCTP_AGENT_DB_NAME] = "\0";
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool set_sctp_agent_db_location(char* db)
|
||||
{
|
||||
if (!db)
|
||||
return false;
|
||||
|
||||
int slen = snprintf(g_sctp_agent_db, MAX_SCTP_AGENT_DB_NAME, "%s", db);
|
||||
if ((slen <= 0) || (slen >= MAX_SCTP_AGENT_DB_NAME))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
char* get_sctp_agent_db_location(void)
|
||||
{
|
||||
return &g_sctp_agent_db[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool get_sctp_agent_info(uint32_t* status_port, uint32_t* status_periodicity)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
|
||||
int port = -1;
|
||||
int periodicity = -1;
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_sctp_agent_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get the port
|
||||
const char *sql = "SELECT passthrough_ctl_port FROM SocketInfo";
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
port = sqlite3_column_int(stmt, 0);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
if (port == -1)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
|
||||
// get the paws status periodicity i.e. how often the status must be sent to the sctp-agent
|
||||
const char *sql2 = "SELECT passthrough_ctl_periodicity FROM Settings";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql2, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
periodicity = sqlite3_column_int(stmt, 0);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
if (periodicity == -1)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// release database
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
*status_port = port;
|
||||
*status_periodicity = periodicity;
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef SCTP_AGENT_DB_INFO_H_
|
||||
#define SCTP_AGENT_DB_INFO_H_
|
||||
|
||||
extern bool set_sctp_agent_db_location(char* db);
|
||||
|
||||
extern char* get_sctp_agent_db_location(void);
|
||||
|
||||
extern bool get_sctp_agent_info(uint32_t* port, uint32_t* status_periodicity);
|
||||
|
||||
|
||||
#endif // SCTP_AGENT_DB_INFO_H_
|
||||
@@ -0,0 +1,34 @@
|
||||
##
|
||||
## Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
## Licensed under the MIT License.
|
||||
##
|
||||
|
||||
include ${PRJROOT}/Makefile.common
|
||||
|
||||
DB_SCHEMA=paws_schema.json
|
||||
COMMON_SRC=common_$(TARGET_PLATFORM).json
|
||||
DEFAULT_SRC=$(COMMON_SRC) gps_$(TARGET_PLATFORM).json devices_$(TARGET_PLATFORM).json
|
||||
|
||||
native_SRC = $(COMMON_SRC) gps_$(TARGET_PLATFORM).json devices_$(TARGET_PLATFORM).json
|
||||
fap_SRC = $(COMMON_SRC) devices_$(TARGET_PLATFORM).json
|
||||
|
||||
|
||||
|
||||
db=paws_$(TARGET_PLATFORM).db
|
||||
|
||||
.PHONY: db
|
||||
db: $(db)
|
||||
|
||||
$(db): $(DB_SCHEMA) $(DEFAULT_SRC)
|
||||
rm -f tmp_db
|
||||
python ../../../libs/sql_db/create_db.py --schema "$(DB_SCHEMA)" --data_l "$($(TARGET_PLATFORM)_SRC)" --o tmp_db
|
||||
cp -f tmp_db $(db)
|
||||
|
||||
.PHONY: natives
|
||||
natives: native1_override.db
|
||||
|
||||
native1_override.db : $(DB_SCHEMA) $(DEFAULT_SRC) override_native.json
|
||||
rm -f tmp_db
|
||||
python ../../../libs/sql_db/create_db.py --schema "$(DB_SCHEMA)" --data_l "$(DEFAULT_SRC) override_native.json" --o tmp_db
|
||||
cp -f tmp_db native1_override.db
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"VersionInfo": {
|
||||
"version": 1
|
||||
},
|
||||
"TVWSDBInfo": {
|
||||
"weblist_host": "http://sandbox-tvws-databases.wsdb.uk",
|
||||
"weblist_filename": "/weblist.json"
|
||||
},
|
||||
"TVWSDBInfoDB": [
|
||||
{
|
||||
"name": "nominet-sandbox",
|
||||
"host": "http://sandbox-paws.wsdb.uk",
|
||||
"token": "your token",
|
||||
"valid": true
|
||||
}
|
||||
],
|
||||
"Settings": {
|
||||
"min_dl_dbm_100k": -30.0,
|
||||
"min_ul_dbm_100k": -30.0,
|
||||
"db_retry_secs": 15,
|
||||
"db_barred_secs": 45,
|
||||
"setting_periodic_secs": 300,
|
||||
"devices_periodic_secs": 60,
|
||||
"gps_periodic_fast_check_secs": 10,
|
||||
"gps_periodic_slow_check_secs": 120,
|
||||
"max_polling_quick_secs": 300
|
||||
},
|
||||
"SettingsLogInfo": {
|
||||
"level": 2,
|
||||
"logname": "/var/log/paws_app_log.txt",
|
||||
"tvwsdb_messages_logname": "/var/log/paws_messages.json",
|
||||
"file_size": "2M",
|
||||
"max_files": 5,
|
||||
"compress": true
|
||||
},
|
||||
"SettingsCloudLogInfo": {
|
||||
"level": 3,
|
||||
"logname": "/var/log/paws_cloud_log.txt",
|
||||
"cloud_ip": "",
|
||||
"port": 8600
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"VersionInfo": {
|
||||
"version": 1
|
||||
},
|
||||
"TVWSDBInfo": {
|
||||
"weblist_host": "http://sandbox-tvws-databases.wsdb.uk",
|
||||
"weblist_filename": "/weblist.json"
|
||||
},
|
||||
"TVWSDBInfoDB": [
|
||||
{
|
||||
"name": "nominet-sandbox",
|
||||
"host": "http://sandbox-paws.wsdb.uk",
|
||||
"token": "your token",
|
||||
"valid": true
|
||||
}
|
||||
],
|
||||
"Settings": {
|
||||
"min_dl_dbm_100k": -30.0,
|
||||
"min_ul_dbm_100k": -30.0,
|
||||
"db_retry_secs": 15,
|
||||
"db_barred_secs": 45,
|
||||
"setting_periodic_secs": 300,
|
||||
"devices_periodic_secs": 60,
|
||||
"gps_periodic_fast_check_secs": 10,
|
||||
"gps_periodic_slow_check_secs": 120,
|
||||
"max_polling_quick_secs": 300
|
||||
},
|
||||
"SettingsLogInfo": {
|
||||
"level": 0,
|
||||
"logname": "tmp/log/paws_app_log.txt",
|
||||
"tvwsdb_messages_logname": "tmp/log/paws_messages.json",
|
||||
"file_size": "10M",
|
||||
"max_files": 10,
|
||||
"compress": true
|
||||
},
|
||||
"SettingsCloudLogInfo": {
|
||||
"level": 3,
|
||||
"logname": "test/log/paws_cloud_log.txt",
|
||||
"cloud_ip": "10.5.1.134 or dns",
|
||||
"port": 8600
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{ }
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"DeviceInfo": [
|
||||
{
|
||||
"deviceid": "test.fap",
|
||||
"manufacturer": "IPAccess",
|
||||
"model": "E40"
|
||||
},
|
||||
{
|
||||
"deviceid": "00101123001003",
|
||||
"manufacturer": "Novatel",
|
||||
"model": "6610L"
|
||||
},
|
||||
{
|
||||
"deviceid": "00101123001001",
|
||||
"manufacturer": "Novatel",
|
||||
"model": "6610L"
|
||||
},
|
||||
{
|
||||
"deviceid": "00101123001002",
|
||||
"manufacturer": "Novatel",
|
||||
"model": "6610L"
|
||||
}
|
||||
],
|
||||
"DeviceInfoAntenna": [
|
||||
{
|
||||
"deviceid": "test.fap",
|
||||
"gain": 4.0
|
||||
}
|
||||
],
|
||||
"DeviceInfoCharacteristics": [
|
||||
{
|
||||
"deviceid": "test.fap",
|
||||
"type": "A",
|
||||
"cat": "master",
|
||||
"emission_class": 3,
|
||||
"technology_id": "AngularJS"
|
||||
},
|
||||
{
|
||||
"deviceid": "00101123001003",
|
||||
"type": "B",
|
||||
"cat": "slave",
|
||||
"emission_class": "5",
|
||||
"technology_id": "AngularJS"
|
||||
},
|
||||
{
|
||||
"deviceid": "00101123001001",
|
||||
"type": "B",
|
||||
"cat": "slave",
|
||||
"emission_class": "5",
|
||||
"technology_id": "AngularJS"
|
||||
},
|
||||
{
|
||||
"deviceid": "00101123001002",
|
||||
"type": "B",
|
||||
"cat": "slave",
|
||||
"emission_class": "5",
|
||||
"technology_id": "AngularJS"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
software/pawsc/paws/SpectrumDBClient/apps/paws/sql_db/femto.db
Executable file
BIN
software/pawsc/paws/SpectrumDBClient/apps/paws/sql_db/femto.db
Executable file
Binary file not shown.
@@ -0,0 +1 @@
|
||||
{ }
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"Gps": [
|
||||
{
|
||||
"deviceid": "test.fap",
|
||||
"fixed": true,
|
||||
"latitude": 52.194903,
|
||||
"longitude": 0.134992,
|
||||
"height": 15,
|
||||
"heightType": "AGL"
|
||||
},
|
||||
{
|
||||
"deviceid": "00101123001001",
|
||||
"fixed": true,
|
||||
"latitude": 52.194903,
|
||||
"longitude": 0.134992,
|
||||
"height": 15,
|
||||
"heightType": "AGL"
|
||||
},
|
||||
{
|
||||
"deviceid": "00101123001002",
|
||||
"fixed": true,
|
||||
"latitude": 52.194903,
|
||||
"longitude": 0.134992,
|
||||
"height": 15,
|
||||
"heightType": "AGL"
|
||||
},
|
||||
{
|
||||
"deviceid": "00101123001003",
|
||||
"fixed": true,
|
||||
"latitude": 52.194903,
|
||||
"longitude": 0.134992,
|
||||
"height": 15,
|
||||
"heightType": "AGL"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"SettingsSpectrumOverride": {
|
||||
"present": true,
|
||||
"bandwidth_rb": 25,
|
||||
"earfcndl": 5205,
|
||||
"earfcnul": 23205,
|
||||
"RefSigPower": -3,
|
||||
"PMax": 10
|
||||
}
|
||||
}
|
||||
BIN
software/pawsc/paws/SpectrumDBClient/apps/paws/sql_db/paws_fap.db
Executable file
BIN
software/pawsc/paws/SpectrumDBClient/apps/paws/sql_db/paws_fap.db
Executable file
Binary file not shown.
BIN
software/pawsc/paws/SpectrumDBClient/apps/paws/sql_db/paws_native.db
Executable file
BIN
software/pawsc/paws/SpectrumDBClient/apps/paws/sql_db/paws_native.db
Executable file
Binary file not shown.
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"VersionInfo": {
|
||||
"version": "INTEGER"
|
||||
},
|
||||
"TVWSDBInfo": {
|
||||
"weblist_host": "VARCHAR(100)",
|
||||
"weblist_filename": "VARCHAR(30)"
|
||||
},
|
||||
"TVWSDBInfoDB": {
|
||||
"name": "VARCHAR(64)",
|
||||
"host": "VARCHAR(100)",
|
||||
"token": "VARCHAR(128)",
|
||||
"valid": "BOOLEAN",
|
||||
"barred_utc": "VARCHAR(64)"
|
||||
},
|
||||
"Settings": {
|
||||
"min_dl_dbm_100k": "FLOAT",
|
||||
"min_ul_dbm_100k": "FLOAT",
|
||||
"db_retry_secs": "INTEGER",
|
||||
"db_barred_secs": "INTEGER",
|
||||
"setting_periodic_secs": "INTEGER",
|
||||
"devices_periodic_secs": "INTEGER",
|
||||
"gps_periodic_fast_check_secs": "INTEGER",
|
||||
"gps_periodic_slow_check_secs": "INTEGER",
|
||||
"max_polling_quick_secs": "INTEGER"
|
||||
},
|
||||
"SettingsLogInfo": {
|
||||
"level": "INTEGER",
|
||||
"logname": "VARCHAR(100)",
|
||||
"tvwsdb_messages_logname": "VARCHAR(100)",
|
||||
"file_size": "VARCHAR(10)",
|
||||
"max_files": "INTEGER",
|
||||
"compress": "BOOLEAN"
|
||||
},
|
||||
"SettingsCloudLogInfo": {
|
||||
"level": "INTEGER",
|
||||
"logname": "VARCHAR(100)",
|
||||
"cloud_ip": "VARCHAR(200)",
|
||||
"port": "INTEGER"
|
||||
},
|
||||
"PreBootState": {
|
||||
"state_str": "VARCHAR(25000)"
|
||||
},
|
||||
"DeviceInfo": {
|
||||
"deviceid": "VARCHAR(30)",
|
||||
"manufacturer": "VARCHAR(30)",
|
||||
"model": "VARCHAR(20)"
|
||||
},
|
||||
"DeviceInfoAntenna": {
|
||||
"deviceid": "VARCHAR(30)",
|
||||
"gain": "FLOAT"
|
||||
},
|
||||
"DeviceInfoCharacteristics": {
|
||||
"deviceid": "VARCHAR(30)",
|
||||
"type": "VARCHAR(2)",
|
||||
"cat": "VARCHAR(7)",
|
||||
"emission_class": "INTEGER",
|
||||
"technology_id": "VARCHAR(7)"
|
||||
},
|
||||
"Gps": {
|
||||
"deviceid": "VARCHAR(30)",
|
||||
"fixed": "BOOLEAN",
|
||||
"latitude": "FLOAT",
|
||||
"longitude": "FLOAT",
|
||||
"height": "INTEGER",
|
||||
"heightType": "VARCHAR(20)"
|
||||
},
|
||||
"SettingsSpectrumOverride": {
|
||||
"present": "BOOLEAN",
|
||||
"bandwidth_rb": "INTEGER",
|
||||
"earfcndl": "INTEGER",
|
||||
"earfcnul": "INTEGER",
|
||||
"RefSigPower": "INTEGER",
|
||||
"PMax": "INTEGER"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
##
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
##
|
||||
|
||||
include ${PRJROOT}/Makefile.common
|
||||
|
||||
APP = sctp-agent
|
||||
C_LIBS += -l4gclient -lm
|
||||
|
||||
INC_DIRS += -I./$(TARGET_PLATFORM)
|
||||
|
||||
## tcps1
|
||||
C_SRC += $(wildcard tcps1/*.c)
|
||||
INC_DIRS += -I./tcps1
|
||||
|
||||
# ifeq ($(TARGET_PLATFORM),native)
|
||||
# CFLAGS += -DTCPS1_TEST
|
||||
# endif
|
||||
|
||||
## if TARGET_PLATFORM = fap or native
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),fap native))
|
||||
C_LIBS += -lsqlite3
|
||||
INC_DIRS += -I./lte_db -I./sctp_agent_db
|
||||
C_SRC += $(wildcard $(TARGET_PLATFORM)/*.c)
|
||||
DB_SRC = $(wildcard sctp_agent_db/*.c)
|
||||
DB_SRC += $(wildcard lte_db/*.c)
|
||||
C_SRC += $(DB_SRC)
|
||||
DEPS = $(patsubst %.o,%.d,$(C_OBJ))
|
||||
endif
|
||||
|
||||
include ${PRJROOT}/rules.mk
|
||||
|
||||
.PHONY: db
|
||||
db:
|
||||
make -C sql_db db
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
// Standard headers
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "tcps1_api.h"
|
||||
|
||||
void tcps1_config(event_callback_func peer_ready_func,
|
||||
socket_send_func passthru_to_enb_func, socket_send_func passthru_to_mme_func, socket_send_func send_to_mme_func,
|
||||
event_callback_func drop_enb_socket_func, event_callback_func drop_mme_socket_func, event_callback_func reset_mme_socket_func,
|
||||
void* logger, void* cloud_logger,
|
||||
device_name_t device_name, device_id_t device_id,
|
||||
uint32_t pkt_ack_guard_ms, uint32_t pkt_retx_max_attempts)
|
||||
{
|
||||
printf("%s: peer_ready_func=%p, passthru_to_enb_func=%p, passthru_to_mme_func=%p, send_to_mme_func=%p, drop_enb_socket_func=%p, drop_mme_socket_func=%p, reset_mme_socket_func=%p, logger=%p, cloud_logger=%p, device_name=%p, device_id=%d, pkt_ack_guard_ms=%d, pkt_retx_max_attempts=%d \n",
|
||||
__func__, peer_ready_func, passthru_to_enb_func, passthru_to_mme_func, send_to_mme_func, drop_enb_socket_func, drop_mme_socket_func, reset_mme_socket_func, logger, cloud_logger, device_name, device_id, pkt_ack_guard_ms, pkt_retx_max_attempts);
|
||||
}
|
||||
|
||||
void tcps1_reset(void)
|
||||
{
|
||||
printf("%s\n", __func__);
|
||||
}
|
||||
|
||||
void tcps1_trigger_reset(void)
|
||||
{
|
||||
printf("%s\n", __func__);
|
||||
}
|
||||
|
||||
void tcps1_free(void)
|
||||
{
|
||||
printf("%s\n", __func__);
|
||||
}
|
||||
|
||||
void tcps1_process_ul(uint8_t* pkt, uint32_t pkt_len)
|
||||
{
|
||||
printf("%s: pkt=%p len=%d\n", __func__, pkt, pkt_len);
|
||||
}
|
||||
|
||||
void tcps1_process_dl(uint8_t* pkt, uint32_t pkt_len)
|
||||
{
|
||||
printf("%s: pkt=%p len=%d\n", __func__, pkt, pkt_len);
|
||||
}
|
||||
|
||||
void tcps1_process_timer_expiry(void)
|
||||
{
|
||||
printf("%s\n", __func__);
|
||||
}
|
||||
|
||||
void tcps1_mme_disconnected(void)
|
||||
{
|
||||
printf("%s\n", __func__);
|
||||
}
|
||||
|
||||
void tcps1_mme_connected(void)
|
||||
{
|
||||
printf("%s\n", __func__);
|
||||
}
|
||||
|
||||
bool tcps1_is_mme_ready(void)
|
||||
{
|
||||
printf("%s\n", __func__);
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
// Platform headers
|
||||
#ifdef _MSC_VER
|
||||
#include <winsock2.h>
|
||||
typedef unsigned socklen_t;
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Standard headers
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "device_db_info.h"
|
||||
|
||||
|
||||
// ##############################################################
|
||||
uint16_t map_mme_sctp_port(uint16_t enb_sctp_port)
|
||||
{
|
||||
// use the same port
|
||||
return enb_sctp_port;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef DEVICE_DB_INFO_H_
|
||||
#define DEVICE_DB_INFO_H_
|
||||
|
||||
#define SCTP_AGENT_DB_LOCATION "/config/sctp_agent.db"
|
||||
#define LTE_DB_LOCATION "/config/femto.db"
|
||||
|
||||
extern uint16_t map_mme_sctp_port(uint16_t enb_sctp_port);
|
||||
|
||||
#endif // DEVICE_DB_INFO_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "lte_db_info.h"
|
||||
|
||||
#define MAX_LTE_DB_NAME (100)
|
||||
static char g_lte_db[MAX_LTE_DB_NAME] = "\0";
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool lte_db_set_location(char* db)
|
||||
{
|
||||
if (!db)
|
||||
return false;
|
||||
|
||||
int slen = snprintf(g_lte_db, MAX_LTE_DB_NAME, "%s", db);
|
||||
if ((slen <= 0) || (slen >= MAX_LTE_DB_NAME))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
char* lte_db_get_location(void)
|
||||
{
|
||||
return &g_lte_db[0];
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool get_device_name(device_name_t device_name)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int rc;
|
||||
|
||||
memset(device_name, 0, sizeof(device_name_t));
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = lte_db_get_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get the DeviceId. We use FAPServiceAccessMgmtLTE.HNBName
|
||||
const char *sql = "SELECT HNBName FROM FAPServiceAccessMgmtLTE";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
char* tmp = (char*)sqlite3_column_text(stmt, 0);
|
||||
if (tmp)
|
||||
{
|
||||
snprintf(device_name, sizeof(device_name_t), "%s", tmp);
|
||||
}
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
// release database
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
static bool get_device_id(device_id_t* device_id)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int rc;
|
||||
|
||||
*device_id = 0;
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = lte_db_get_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get the DeviceId. We use FAPServiceAccessMgmtLTE.HNBName
|
||||
const char *sql = "SELECT CellIdentity FROM FAPServiceCellConfigLTERANCommon";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
*device_id = sqlite3_column_int(stmt, 0);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
// release database
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool lte_db_get_enb_info(int *port, device_name_t device_name, device_id_t *device_id)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
*port = -1;
|
||||
|
||||
if (!(get_device_name(device_name)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
if (!(get_device_id(device_id)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = lte_db_get_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// #################################################################################################################
|
||||
// get the sctp port used for the eNB software to connect to the SCTP database
|
||||
const char *sql = "SELECT S1SigLinkPort FROM FAPServiceFAPControlLTEGateway";
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
*port = sqlite3_column_int(stmt, 0);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
// release database
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool lte_db_get_RxTxStatus(int *tx_status)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = lte_db_get_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// #################################################################################################################
|
||||
// get the sctp port used for the eNB software to connect to the SCTP database
|
||||
const char *sql = "SELECT RFTxStatus FROM FAPServiceFAPControlLTE";
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
*tx_status = sqlite3_column_int(stmt, 0);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
// release database
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef LTE_DB_INFO_H_
|
||||
#define LTE_DB_INFO_H_
|
||||
|
||||
#include "utils/types.h"
|
||||
|
||||
extern bool lte_db_set_location(char* db);
|
||||
|
||||
extern char* lte_db_get_location(void);
|
||||
|
||||
extern bool lte_db_get_enb_info(int *port, device_name_t device_name, device_id_t *device_id);
|
||||
|
||||
extern bool lte_db_get_RxTxStatus(int *tx_status);
|
||||
|
||||
|
||||
#endif // LTE_DB_INFO_H_
|
||||
108
software/pawsc/paws/SpectrumDBClient/apps/sctp-agent/main.c
Normal file
108
software/pawsc/paws/SpectrumDBClient/apps/sctp-agent/main.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
// Platform headers
|
||||
#ifdef _MSC_VER
|
||||
#include <winsock2.h>
|
||||
typedef unsigned socklen_t;
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Standard headers
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "device_db_info.h"
|
||||
#include "lte_db_info.h"
|
||||
#include "sctp_agent_db_info.h"
|
||||
#include "sctp_agent.h"
|
||||
|
||||
|
||||
#define sctp_fatal_error(msg, ...) \
|
||||
{ \
|
||||
fprintf(stderr, "FATAL ERROR in %s, line %d: ", __FILE__, __LINE__); \
|
||||
printf(msg, ##__VA_ARGS__); \
|
||||
putchar('\n'); \
|
||||
exit(-1); \
|
||||
}
|
||||
|
||||
#define sctp_fatal_perror(msg) \
|
||||
{ \
|
||||
fprintf(stderr, "FATAL ERROR in %s, line %d: ", __FILE__, __LINE__); \
|
||||
perror(msg); \
|
||||
exit(-1); \
|
||||
}
|
||||
|
||||
// Cfg
|
||||
sctp_agent_cfg_t g_sctp_agent_cfg;
|
||||
|
||||
// globals
|
||||
device_name_t gDeviceName = { 0 };
|
||||
device_id_t gDeviceId = 0;
|
||||
|
||||
|
||||
// #########################################################################################################
|
||||
static void get_database_configs(void)
|
||||
{
|
||||
if (!(set_sctp_agent_db_location(SCTP_AGENT_DB_LOCATION)))
|
||||
sctp_fatal_error("Cant set SCTP-AGENT-DB location");
|
||||
|
||||
if (!(lte_db_set_location(LTE_DB_LOCATION)))
|
||||
sctp_fatal_error("Cant set Device-DB location");
|
||||
|
||||
// loop until the SCTP settings are read correctly
|
||||
while (1)
|
||||
{
|
||||
if ((get_sctp_agent_cfg(&g_sctp_agent_cfg)))
|
||||
break;
|
||||
sleep(1); // try in a second
|
||||
}
|
||||
|
||||
// loop until the LTE-DB settings are read correctly
|
||||
while (1)
|
||||
{
|
||||
int port = -1;
|
||||
if (lte_db_get_enb_info(&port, gDeviceName, &gDeviceId))
|
||||
{
|
||||
g_sctp_agent_cfg.socket_info.enb_sctp_port = port;
|
||||
break;
|
||||
}
|
||||
sleep(1); // try in a second
|
||||
}
|
||||
|
||||
// use the same SCTP port as the destination MME SCTP port
|
||||
g_sctp_agent_cfg.socket_info.mme_sctp_port = map_mme_sctp_port(g_sctp_agent_cfg.socket_info.enb_sctp_port);
|
||||
}
|
||||
|
||||
|
||||
// #########################################################################################################
|
||||
int main()
|
||||
{
|
||||
// wait a while for other services to come up
|
||||
sleep(10);
|
||||
|
||||
memset(&g_sctp_agent_cfg, 0, sizeof(sctp_agent_cfg_t));
|
||||
|
||||
// this will loop until the databases are read
|
||||
get_database_configs();
|
||||
|
||||
// it wont return from the function unless there is a failure
|
||||
sctp_agent_run(&g_sctp_agent_cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
// Platform headers
|
||||
#ifdef _MSC_VER
|
||||
#include <winsock2.h>
|
||||
typedef unsigned socklen_t;
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "mme_address.h"
|
||||
#include "sctp_globals.h"
|
||||
#include "sctp_agent_db_info.h"
|
||||
|
||||
|
||||
// MME address info
|
||||
static mme_address_list_t* mme_address_list = NULL; // address list
|
||||
// current MME DNS info
|
||||
static struct addrinfo *mme_servinfo = NULL;
|
||||
static bool dns_triggered = false; // do DNS next time we try and open socket
|
||||
|
||||
|
||||
|
||||
static bool mme_address_dns_lookup(int protocol, int port)
|
||||
{
|
||||
char* mme_addr = NULL;
|
||||
|
||||
// release current servinfo
|
||||
if (mme_servinfo)
|
||||
{
|
||||
freeaddrinfo(mme_servinfo);
|
||||
mme_servinfo = NULL;
|
||||
}
|
||||
|
||||
if (!(mme_addr = mme_address_get_head_addr()))
|
||||
goto error_hdl;
|
||||
|
||||
LOG_PRINT(LOG_NOTICE, "Doing dns lookup for [addr=%s]", mme_addr);
|
||||
|
||||
// init the hints
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = protocol;
|
||||
|
||||
// convert port to a string
|
||||
char snum[7];
|
||||
snprintf(snum, sizeof(snum), "%d", port);
|
||||
|
||||
if ((getaddrinfo(mme_addr, snum, &hints, &mme_servinfo)) != 0)
|
||||
{
|
||||
LOG_PRINT(LOG_ERROR, "Failure from getaddrinfo [addr=%s]", mme_addr);
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
LOG_PRINT(LOG_NOTICE, "Successful dns-lookup for [addr=%s]", mme_addr);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (mme_servinfo)
|
||||
freeaddrinfo(mme_servinfo);
|
||||
mme_servinfo = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
// add as circular list
|
||||
bool mme_address_list_add(mme_address_t* addr)
|
||||
{
|
||||
if (!addr)
|
||||
return false;
|
||||
|
||||
if (!mme_address_list)
|
||||
{
|
||||
if (!(mme_address_list = calloc(1, sizeof(mme_address_list_t))))
|
||||
return false;
|
||||
}
|
||||
|
||||
mme_address_t* tail = NULL;
|
||||
|
||||
if (mme_address_list->head == NULL)
|
||||
{
|
||||
mme_address_list->head = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
tail = mme_address_list->head;
|
||||
while (tail->next != mme_address_list->head)
|
||||
tail = tail->next;
|
||||
tail->next = addr;
|
||||
}
|
||||
addr->next = mme_address_list->head;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void mme_address_list_free(void)
|
||||
{
|
||||
if (!mme_address_list)
|
||||
return;
|
||||
|
||||
mme_address_t *head = mme_address_list->head;
|
||||
mme_address_t *curr = mme_address_list->head;
|
||||
if (!curr)
|
||||
return; // nothing in list
|
||||
|
||||
while (mme_address_list->head != head)
|
||||
{
|
||||
curr = mme_address_list->head;
|
||||
mme_address_list->head = curr->next;
|
||||
free(curr);
|
||||
}
|
||||
mme_address_list->head = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
char* mme_address_list_get_curr(void)
|
||||
{
|
||||
if ((!mme_address_list) || (!mme_address_list->head))
|
||||
return NULL;
|
||||
mme_address_t* head = mme_address_list->head;
|
||||
return head->mme_addr;
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
// returns True if address actually changes
|
||||
bool mme_address_list_goto_next(void)
|
||||
{
|
||||
bool ret = false;
|
||||
if (!mme_address_list)
|
||||
return ret;
|
||||
|
||||
if (mme_address_list->head)
|
||||
{
|
||||
ret = (mme_address_list->head != mme_address_list->head->next);
|
||||
mme_address_list->head = mme_address_list->head->next;
|
||||
if (ret)
|
||||
mme_address_write_head_to_db(mme_address_list->head->mme_addr);
|
||||
}
|
||||
|
||||
// trigger DNS
|
||||
dns_triggered = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
// Set the head to the address in use. Retunr TRUE is present
|
||||
int mme_address_list_set_head(char* in_use)
|
||||
{
|
||||
if (!mme_address_list)
|
||||
return 0;
|
||||
|
||||
if ((!in_use) || (strlen(in_use) == 0))
|
||||
return 0;
|
||||
|
||||
mme_address_t *head = mme_address_list->head;
|
||||
mme_address_t *curr = mme_address_list->head;
|
||||
if (!curr)
|
||||
return 0; // nothing in list
|
||||
|
||||
// move to position after head, and then walk until we're back to head
|
||||
curr = curr->next;
|
||||
while (curr != head)
|
||||
{
|
||||
if (strcmp(in_use, curr->mme_addr) == 0)
|
||||
{
|
||||
mme_address_list->head = curr;
|
||||
break;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
mme_address_write_head_to_db(mme_address_list->head->mme_addr);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
char* mme_address_get_head_addr()
|
||||
{
|
||||
if ((!mme_address_list) || (!mme_address_list->head) || (!mme_address_list->head->mme_addr) || (strlen(mme_address_list->head->mme_addr) == 0))
|
||||
{
|
||||
LOG_PRINT(LOG_ERROR, "No MME address head defined\n");
|
||||
return NULL;
|
||||
}
|
||||
return mme_address_list->head->mme_addr;
|
||||
}
|
||||
|
||||
|
||||
// #########################################################################################################
|
||||
int32_t mme_address_make_outgoing_socket(const char *addr_str, uint16_t port, int protocol)
|
||||
{
|
||||
LOG_PRINT(LOG_FUNC, "addr=%s port=%d\n", addr_str, port);
|
||||
|
||||
int32_t sockfd = -1;
|
||||
|
||||
// do DNS if not done yet
|
||||
if ((!mme_servinfo) || (dns_triggered))
|
||||
{
|
||||
dns_triggered = false;
|
||||
if (!mme_address_dns_lookup(protocol, port))
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// loop through all the results and connect to the first we can
|
||||
struct addrinfo *p = NULL;
|
||||
for (p = mme_servinfo; p != NULL; p = p->ai_next)
|
||||
{
|
||||
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (protocol == IPPROTO_TCP)
|
||||
{
|
||||
int flag = 1;
|
||||
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
|
||||
}
|
||||
|
||||
|
||||
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
|
||||
{
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break; // if we get here, we must have connected successfully
|
||||
}
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
// looped off the end of the list with no connection
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
return sockfd;
|
||||
|
||||
error_hdl:
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef MME_ADDRESS_INFO_H_
|
||||
#define MME_ADDRESS_INFO_H_
|
||||
|
||||
#include "utils/types.h"
|
||||
|
||||
typedef struct mme_address {
|
||||
host_addr_t mme_addr;
|
||||
struct mme_address *next;
|
||||
} mme_address_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mme_address_t *head;
|
||||
} mme_address_list_t;
|
||||
|
||||
extern bool mme_address_list_add(mme_address_t* addr);
|
||||
extern void mme_address_list_free(void);
|
||||
extern char* mme_address_list_get_curr(void);
|
||||
extern bool mme_address_list_goto_next(void);
|
||||
extern int mme_address_list_set_head(char* in_use);
|
||||
extern char* mme_address_get_head_addr(void);
|
||||
extern int32_t mme_address_make_outgoing_socket(const char *addr_str, uint16_t port, int protocol);
|
||||
|
||||
#endif // SCTP_AGENT_DB_INFO_H_
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
// Platform headers
|
||||
#ifdef _MSC_VER
|
||||
#include <winsock2.h>
|
||||
typedef unsigned socklen_t;
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Standard headers
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "device_db_info.h"
|
||||
|
||||
|
||||
// ##############################################################
|
||||
uint16_t map_mme_sctp_port(uint16_t enb_sctp_port)
|
||||
{
|
||||
// use the same port
|
||||
return enb_sctp_port;
|
||||
|
||||
// return enb_sctp_port + 1; // Use a different port if testing on the local VirtualBox VM.
|
||||
// This allows a test mme to be run on the VM at the same time
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef DEVICE_DB_INFO_H_
|
||||
#define DEVICE_DB_INFO_H_
|
||||
|
||||
#define SCTP_AGENT_DB_LOCATION "./sql_db/sctp_agent_native.db"
|
||||
#define LTE_DB_LOCATION "./sql_db/femto.db"
|
||||
|
||||
extern uint16_t map_mme_sctp_port(uint16_t enb_sctp_port);
|
||||
|
||||
#endif // DEVICE_DB_INFO_H_
|
||||
|
||||
|
||||
1162
software/pawsc/paws/SpectrumDBClient/apps/sctp-agent/sctp_agent.c
Normal file
1162
software/pawsc/paws/SpectrumDBClient/apps/sctp-agent/sctp_agent.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef SCTP_AGENT_
|
||||
#define SCTP_AGENT_
|
||||
|
||||
#include "sctp_agent_db_info.h"
|
||||
|
||||
extern void sctp_agent_run(sctp_agent_cfg_t* g_sctp_agent_cfg);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include "sctp_agent_db_info.h"
|
||||
|
||||
#include "mme_address.h"
|
||||
|
||||
|
||||
#define MAX_SCTP_AGENT_DB_NAME (100)
|
||||
static char g_sctp_agent_db[MAX_SCTP_AGENT_DB_NAME] = "\0";
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
bool set_sctp_agent_db_location(char* db)
|
||||
{
|
||||
if (!db)
|
||||
return false;
|
||||
|
||||
int slen = snprintf(g_sctp_agent_db, MAX_SCTP_AGENT_DB_NAME, "%s", db);
|
||||
if ((slen <= 0) || (slen >= MAX_SCTP_AGENT_DB_NAME))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
char* get_sctp_agent_db_location(void)
|
||||
{
|
||||
return &g_sctp_agent_db[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ########################################################################
|
||||
static bool read_CloudLogInfo(sqlite3 *sql_hdl, cloud_logger_cfg_t* log_cfg)
|
||||
{
|
||||
if ((!sql_hdl) || (!log_cfg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memset(log_cfg, 0, sizeof(cloud_logger_cfg_t));
|
||||
|
||||
const char *zSql = "SELECT * FROM SettingsCloudLogInfo";
|
||||
int pnRow; /* Number of result rows written here */
|
||||
int pnColumn; /* Number of result columns written here */
|
||||
char *pzErrmsg = NULL;
|
||||
char **pazResult = NULL;
|
||||
int rc = sqlite3_get_table(
|
||||
sql_hdl, /* An open database */
|
||||
zSql, /* SQL to be evaluated */
|
||||
&pazResult, /* Results of the query */
|
||||
&pnRow, /* Number of result rows written here */
|
||||
&pnColumn, /* Number of result columns written here */
|
||||
&pzErrmsg /* Error msg written here */
|
||||
);
|
||||
|
||||
if (!((rc == SQLITE_OK) && (pnRow == 1) && (pnColumn == 4)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
for (int row = 0; row < pnRow; row++)
|
||||
{
|
||||
for (int col = 0; col < pnColumn; col++)
|
||||
{
|
||||
int index = (row * pnColumn) + pnColumn + col;
|
||||
if (strcmp(pazResult[col], "level") == 0)
|
||||
log_cfg->level = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "logname") == 0)
|
||||
{
|
||||
if (pazResult[index])
|
||||
strcpy(log_cfg->logname, pazResult[index]);
|
||||
}
|
||||
else if (strcmp(pazResult[col], "port") == 0)
|
||||
log_cfg->port = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "cloud_ip") == 0)
|
||||
{
|
||||
if (pazResult[index])
|
||||
strcpy(log_cfg->cloud_addr, pazResult[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (pazResult)
|
||||
sqlite3_free_table(pazResult);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (pazResult) sqlite3_free_table(pazResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ########################################################################
|
||||
static bool read_LogInfo(sqlite3 *sql_hdl, logger_cfg_t* loginfo)
|
||||
{
|
||||
if ((!sql_hdl) || (!loginfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memset(loginfo, 0, sizeof(logger_cfg_t));
|
||||
|
||||
const char *zSql = "SELECT * FROM SettingsLogInfo";
|
||||
int pnRow; /* Number of result rows written here */
|
||||
int pnColumn; /* Number of result columns written here */
|
||||
char *pzErrmsg = NULL;
|
||||
char **pazResult = NULL;
|
||||
int rc = sqlite3_get_table(
|
||||
sql_hdl, /* An open database */
|
||||
zSql, /* SQL to be evaluated */
|
||||
&pazResult, /* Results of the query */
|
||||
&pnRow, /* Number of result rows written here */
|
||||
&pnColumn, /* Number of result columns written here */
|
||||
&pzErrmsg /* Error msg written here */
|
||||
);
|
||||
|
||||
if (!((rc == 0) && (pnRow == 1) && (pnColumn == 5)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
for (int row = 0; row < pnRow; row++)
|
||||
{
|
||||
for (int col = 0; col < pnColumn; col++)
|
||||
{
|
||||
int index = (row * pnColumn) + pnColumn + col;
|
||||
if (strcmp(pazResult[col], "level") == 0)
|
||||
loginfo->level = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "logname") == 0)
|
||||
strcpy(loginfo->logname, pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "file_size") == 0)
|
||||
strcpy(loginfo->size, pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "max_files") == 0)
|
||||
loginfo->max = atoi(pazResult[index]);
|
||||
else if (strcmp(pazResult[col], "compress") == 0)
|
||||
loginfo->compress = (bool)(pazResult[index]);
|
||||
else
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (pazResult)
|
||||
sqlite3_free_table(pazResult);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (pazResult) sqlite3_free_table(pazResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
void mme_address_write_head_to_db(char* mme_addr)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
char sql_str[200];
|
||||
|
||||
if ((!mme_addr) || (strlen(mme_addr) == 0))
|
||||
return;
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_sctp_agent_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// build SQL command
|
||||
sprintf(sql_str, "UPDATE SocketInfo set SocketInfoMmeCurrent='%s'", mme_addr);
|
||||
char* error_msg = NULL;
|
||||
int rc = sqlite3_exec(sql_hdl, sql_str, NULL, NULL, &error_msg);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
error_hdl:
|
||||
// free up resources
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
// note this does not populate "enb_sctp_port". This parameter is read from the LTE DB
|
||||
//
|
||||
static bool get_mme_address_list(void)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
mme_address_t* mme_address = NULL;
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_sctp_agent_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get the MME addresses
|
||||
const char *sql = "SELECT ip_address FROM SocketInfoMmeList";
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
if (!(mme_address = calloc(1,sizeof(mme_address_t))))
|
||||
goto error_hdl;
|
||||
char *tmp;
|
||||
tmp = (char*)sqlite3_column_text(stmt, 0); strcpy(mme_address->mme_addr, tmp);
|
||||
|
||||
// check that mme address is actually populated
|
||||
if (strlen(mme_address->mme_addr) == 0)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// add to list
|
||||
if (!(mme_address_list_add(mme_address)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
mme_address = NULL;
|
||||
}
|
||||
|
||||
// get the Current address in use
|
||||
char in_use[200];
|
||||
in_use[0] = 0;
|
||||
const char *sql2 = "SELECT SocketInfoMmeCurrent FROM SocketInfo";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql2, -1, &stmt, NULL);
|
||||
if (rc == SQLITE_OK)
|
||||
{
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
char* tmp = (char*)sqlite3_column_text(stmt, 0);
|
||||
if ((tmp) && (strlen(tmp) > 0))
|
||||
{
|
||||
strcpy(in_use, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free up resources
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
// update database
|
||||
int curr_written = 0;
|
||||
if (strlen(in_use) > 0)
|
||||
{
|
||||
curr_written = mme_address_list_set_head(in_use);
|
||||
}
|
||||
|
||||
if (!curr_written)
|
||||
{
|
||||
// use head as "current"
|
||||
char *mme_addr = mme_address_get_head_addr();
|
||||
if (!mme_addr)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
mme_address_write_head_to_db(mme_addr);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (mme_address) free(mme_address);
|
||||
mme_address_list_free();
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#######################################################################################
|
||||
// note this does not populate "enb_sctp_port". This parameter is read from the LTE DB
|
||||
//
|
||||
bool get_sctp_agent_cfg(sctp_agent_cfg_t* cfg)
|
||||
{
|
||||
sqlite3 *sql_hdl = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
|
||||
if (!cfg)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// get datafile location and open it
|
||||
char* db_sql_file = get_sctp_agent_db_location();
|
||||
if (!db_sql_file)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// #################################################################################################################
|
||||
// get the socket info
|
||||
const char *sql = "SELECT passthrough_ctl_port, mme_connection_type FROM SocketInfo";
|
||||
int rc = sqlite3_prepare_v2(sql_hdl, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
char *tmp;
|
||||
cfg->socket_info.passthrough_ctl_port = sqlite3_column_int(stmt, 0);
|
||||
tmp = (char*)sqlite3_column_text(stmt, 1); cfg->socket_info.mme_conn_type = (strcmp(tmp, "sctp") == 0) ? CONN_SCTP : CONN_TCP;
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
|
||||
// release database - release here as we might write to the dateabase in get_mme_address_list
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
sql_hdl = NULL;
|
||||
if (!(get_mme_address_list()))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
sqlite3_open(db_sql_file, &sql_hdl);
|
||||
if (!sql_hdl)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// #################################################################################################################
|
||||
// get the log info
|
||||
if (!(read_LogInfo(sql_hdl, &cfg->log_info)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
|
||||
// #################################################################################################################
|
||||
// get the log info
|
||||
if (!(read_CloudLogInfo(sql_hdl, &cfg->cloud_log_info)))
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
// copy cloud level
|
||||
cfg->log_info.cloud_level = cfg->cloud_log_info.level;
|
||||
|
||||
|
||||
// #################################################################################################################
|
||||
// get the paws status periodicity i.e. how often the status must be sent to the sctp-agent
|
||||
const char *sql2 = "SELECT use_passthrough_ctl, passthrough_ctl_periodicity, azure_mme_socket_retry_s, azure_mme_socket_drop_enb_s, azure_mme_socket_swap_mme_s, azure_mme_pkt_retx_guard_ms, azure_mme_pkt_retx_max_attempts FROM Settings";
|
||||
rc = sqlite3_prepare_v2(sql_hdl, sql2, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
cfg->settings.use_passthrough_ctl = (bool)sqlite3_column_int(stmt, 0);
|
||||
cfg->settings.passthrough_ctl_periodicity = sqlite3_column_int(stmt, 1);
|
||||
cfg->settings.azure_mme_socket_retry_s = sqlite3_column_int(stmt, 2);
|
||||
cfg->settings.azure_mme_socket_drop_enb_s = sqlite3_column_int(stmt, 3);
|
||||
cfg->settings.azure_mme_socket_swap_mme_s = sqlite3_column_int(stmt, 4);
|
||||
cfg->settings.azure_mme_pkt_retx_guard_ms = sqlite3_column_int(stmt, 5);
|
||||
cfg->settings.azure_mme_pkt_retx_max_attempts = sqlite3_column_int(stmt, 6);
|
||||
}
|
||||
if (rc != SQLITE_DONE)
|
||||
{
|
||||
goto error_hdl;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt); stmt = NULL;
|
||||
|
||||
// validate settings
|
||||
if (cfg->settings.azure_mme_socket_retry_s < AZURE_MME_SOCKET_RETRY_S_MIN)
|
||||
cfg->settings.azure_mme_socket_retry_s = AZURE_MME_SOCKET_RETRY_S_MIN;
|
||||
if (cfg->settings.azure_mme_pkt_retx_guard_ms < AZURE_MME_PKT_GUARD_MS_MIN)
|
||||
cfg->settings.azure_mme_pkt_retx_guard_ms = AZURE_MME_PKT_GUARD_MS_MIN;
|
||||
|
||||
// release database
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
|
||||
return true;
|
||||
|
||||
error_hdl:
|
||||
if (sql_hdl) sqlite3_close(sql_hdl);
|
||||
if (stmt) sqlite3_finalize(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef SCTP_AGENT_DB_INFO_H_
|
||||
#define SCTP_AGENT_DB_INFO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils/types.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
#include "mme_address.h"
|
||||
#include "sctp_agent_db_info.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONN_SCTP = 0,
|
||||
CONN_TCP
|
||||
} mme_conn_type_e;
|
||||
|
||||
#define AZURE_MME_SOCKET_RETRY_S_MIN (1)
|
||||
#define AZURE_MME_PKT_GUARD_MS_MIN (20)
|
||||
|
||||
typedef struct {
|
||||
uint16_t passthrough_ctl_port;
|
||||
uint16_t enb_sctp_port;
|
||||
uint16_t mme_sctp_port;
|
||||
mme_conn_type_e mme_conn_type;
|
||||
} sctp_agent_socket_cfg_t;
|
||||
|
||||
typedef struct {
|
||||
bool use_passthrough_ctl;
|
||||
uint32_t passthrough_ctl_periodicity;
|
||||
uint32_t azure_mme_socket_retry_s; // how often to try to re-open a socket to MME
|
||||
uint32_t azure_mme_socket_drop_enb_s; // duration of a socket being disconnected which will cause an eNB socket drop and RESET
|
||||
uint32_t azure_mme_socket_swap_mme_s; // duration of a socket being disconnected which will cause an attempt to swap MME
|
||||
uint32_t azure_mme_pkt_retx_guard_ms; // how long to wait for packet acknowledgement , before doing a retx
|
||||
uint32_t azure_mme_pkt_retx_max_attempts; // max number of retx (not including initial tx). At max attempts, MME socket is dropped
|
||||
} sctp_agent_settings_cfg_t;
|
||||
|
||||
typedef struct {
|
||||
sctp_agent_socket_cfg_t socket_info;
|
||||
sctp_agent_settings_cfg_t settings;
|
||||
logger_cfg_t log_info;
|
||||
cloud_logger_cfg_t cloud_log_info;
|
||||
} sctp_agent_cfg_t;
|
||||
|
||||
|
||||
extern bool set_sctp_agent_db_location(char* db);
|
||||
|
||||
extern char* get_sctp_agent_db_location(void);
|
||||
|
||||
extern bool get_sctp_agent_cfg(sctp_agent_cfg_t* cfg); // note this does not populate "enb_sctp_port"
|
||||
|
||||
extern void mme_address_write_head_to_db(char* mme_addr);
|
||||
|
||||
#endif // SCTP_AGENT_DB_INFO_H_
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef SCTP_CFG_OPTIONS_H_
|
||||
#define SCTP_CFG_OPTIONS_H_
|
||||
|
||||
|
||||
#define REBOOT_AFTER_RFTXSTATUS_DROP // some FAPs do not automatically restart the radio once it had been turned off.
|
||||
// With this setting, we will force a reboot if the eNB socket is opened folliwng a radio drop.
|
||||
|
||||
|
||||
|
||||
#endif // SCTP_CFG_OPTIONS_H_
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef SCTP_GLOBALS_H_
|
||||
#define SCTP_GLOBALS_H_
|
||||
|
||||
#include "utils/types.h"
|
||||
#include "utils/utils.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
#include "sctp_cfg_options.h"
|
||||
|
||||
// reference to globals
|
||||
extern device_name_t gDeviceName;
|
||||
extern device_id_t gDeviceId;
|
||||
extern void* g_logger;
|
||||
extern void* g_cloud_logger;
|
||||
|
||||
#define SCTP_LOGGER_TYPE "SCTPAGENT"
|
||||
|
||||
#define MAX_LOG_LINE_LENGTH (200)
|
||||
static char logline_[MAX_LOG_LINE_LENGTH];
|
||||
#define LOG_PRINT(loglevel, fmt, args...) { \
|
||||
if (g_logger) \
|
||||
{ \
|
||||
int slen = snprintf(logline_, MAX_LOG_LINE_LENGTH, fmt, ##args); \
|
||||
if (!((slen <= 0) || (slen >= MAX_LOG_LINE_LENGTH))) \
|
||||
{ \
|
||||
logger_log(g_logger, logline_, loglevel, SCTP_LOGGER_TYPE, true, true, __FILENAME__, __LINE__, __func__, g_cloud_logger, gDeviceName, SCTP_LOGGER_TYPE); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define sctp_fatal_error(fmt, args...) { \
|
||||
LOG_PRINT(LOG_CRITICAL, fmt, ##args); \
|
||||
fatal_error("%s %d " fmt, __FILE__, __LINE__, ##args) \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // SCTP_GLOBALS_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user