Replace generate interface documentation script and improve interfaces docs

This commit is contained in:
Simon Stürz 2018-12-05 14:54:40 +01:00 committed by Michael Zanetti
parent c79908f1e2
commit 6f1e22546a
5 changed files with 312 additions and 35 deletions

216
doc/generate-interfaces-qdoc.py Executable file
View File

@ -0,0 +1,216 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# #
# Copyright (C) 2018 Simon Stuerz <simon.stuerz@guh.io> #
# #
# This file is part of nymea. #
# #
# nymea is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, version 2 of the License. #
# #
# nymea is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with nymea. If not, see <http://www.gnu.org/licenses/>. #
# #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
import argparse
import traceback
import json
import os
import sys
import subprocess
__version__='1.0.0'
#--------------------------------------------------------------------------
def printInfo(info):
print('[+] ' + info)
#--------------------------------------------------------------------------
def printWarning(warning):
print('[-] Warning: ' + warning)
#--------------------------------------------------------------------------
def printError(error):
print('[!] Error: ' + error)
#--------------------------------------------------------------------------
def writeToFile(line):
outputFile.write('%s\n' % line)
#--------------------------------------------------------------------------
def writeCodeSection(jsonData):
writeToFile('\code')
writeToFile(json.dumps(jsonData, sort_keys=True, indent=4))
writeToFile('\endcode')
writeToFile('')
#--------------------------------------------------------------------------
def loadInterfaces():
printInfo('Loading interfaces files from %s' % interfacesDirectory)
interfaces = {}
interfaceFiles = []
# Read the file list
for fileName in os.listdir(interfacesDirectory):
if ".json" in fileName:
interfaceFiles.append(interfacesDirectory + "/" + fileName)
# Sort file lists for beeing able to get the last n days logs
interfaceFiles.sort()
for fileName in interfaceFiles:
name = os.path.basename(fileName)
interfaceName = os.path.splitext(name)[0]
#printInfo(' %s --> %s | %s' % (interfaceName, name, fileName))
interfaces[interfaceName] = loadJsonData(fileName)
return interfaces
#--------------------------------------------------------------------------
def loadJsonData(fileName):
# Open the file
try:
jsonFile = open(fileName, 'r')
except:
printError('Could not open JSON file \"%s\"' % (fileName))
exit(-1)
jsonFileContent = jsonFile.read()
jsonFile.close()
# Parse json content
try:
data = json.loads(jsonFileContent)
except ValueError as error:
printError('Could not load json content from %s' % (fileName))
printError(' %s' % (error))
exit(-1)
return data
#--------------------------------------------------------------------------
def writeDocumentationContent():
printInfo('Write interfaces documentation content to %s' % outputFileName)
writeToFile('\section1 Available interfaces')
writeToFile('This following list shows you the current available interfaces.')
writeToFile('')
# Create the interfaces list
writeToFile('\list')
for interfaceName in interfaceNames:
writeToFile(' \li \l{%s}' % interfaceName)
writeToFile('\endlist')
writeToFile('')
writeToFile('')
# Extract interface information
writeInterfaces()
#--------------------------------------------------------------------------
def writeInterfaces():
for interfaceName in interfaceNames:
writeToFile('\section2 %s' % interfaceName)
interfaceJson = interfaces[interfaceName]
# If a desciption is provided, use it and remove it from the map
if 'description' in interfaceJson:
writeToFile('%s' % interfaceJson['description'] )
interfaceJson.pop('description')
writeCodeSection(interfaceJson)
writeToFile('')
writeExtends(interfaceJson)
writeToFile('')
#--------------------------------------------------------------------------
def writeExtends(interfaceJson):
if 'extends' in interfaceJson:
if type(interfaceJson['extends']) is list:
#printInfo('extends is list: %s' % interfaceJson['extends'])
extendsList = list(interfaceJson['extends'])
extendsString = "See also: "
extendsCount = len(extendsList)
for i in range(len(extendsList)):
if i is extendsCount - 1:
extendsString += '\l{%s}' % extendsList[i]
else:
extendsString += '\l{%s}, ' % extendsList[i]
writeToFile(extendsString)
else:
#printInfo('extends is string: %s' % interfaceJson['extends'])
writeToFile('See also: \l{%s}' % interfaceJson['extends'])
###########################################################################
# Main
###########################################################################
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='This tool generates a qdoc file out of the interfaces JSON files for the online documentation.')
parser.add_argument('-v', '--version', action='version', version=__version__)
parser.add_argument('-i', '--interfaces', help='The path to the interfaces JSON files. Default is ../libnymea/interfaces/', metavar='path', default='../libnymea/interfaces/')
parser.add_argument('-o', '--output', help='The qdoc output file with the generated documentation script. Default is interfacelist.qdoc', metavar='output', default='interfacelist.qdoc')
args = parser.parse_args()
interfacesDirectory = os.path.abspath(args.interfaces)
outputFileName = os.path.dirname(os.path.realpath(sys.argv[0])) + "/" + args.output
# Print build information for debugging
printInfo('--> Interfaces directory: %s' % interfacesDirectory)
printInfo('--> Output: %s' % outputFileName)
# Verify interfaces path
if not os.path.isdir(interfacesDirectory):
printError('The given interfaces directory path does not exist \"%s\"' % (interfacesDirectory))
exit(-1)
# Open qdoc file for writing
try:
outputFile = open(outputFileName, 'w')
except:
printError('Could not open output file \"%s\"' % (outputFileName))
exit(-1)
# Load all interface files
interfaces = loadInterfaces()
# Get a alphabetic sorted list of interfaces
interfaceNames = interfaces.keys()
interfaceNames.sort()
# Write the documentation
writeDocumentationContent()
outputFile.close()
printInfo('Done.')

View File

@ -29,10 +29,6 @@
A dimmablelight extends this type and adds a brightness property to it. This means, if a DeviceClass implements \l {dimmablelight},
it also needs to cater for the \l {light} interface's states.
\section1 Available interfaces
This following list shows you the current available interfaces.
\include interfacelist.qdoc
*/

View File

@ -1,5 +1,5 @@
/*!
In the following section you can find a detaild description of the current API version 1.7.
In the following section you can find a detaild description of the current API version 1.10.
\list
\li \l{Types}
\li \l{Methods}
@ -78,6 +78,15 @@ See also: \l{ParamType}
}
\endcode
See also: \l{RepeatingOption}
\section2 CloudConnectionState
\code
[
"CloudConnectionStateDisabled",
"CloudConnectionStateUnconfigured",
"CloudConnectionStateConnecting",
"CloudConnectionStateConnected"
]
\endcode
\section2 ConfigurationError
\code
[
@ -644,7 +653,12 @@ See also: \l{Unit}, \l{BasicType}
\section2 TagError
\code
"$ref:TagError"
[
"TagErrorNoError",
"TagErrorDeviceNotFound",
"TagErrorRuleNotFound",
"TagErrorTagNotFound"
]
\endcode
\section2 TimeDescriptor
\code
@ -729,7 +743,9 @@ See also: \l{RepeatingOption}
"UnitMilliVolt",
"UnitVoltAmpere",
"UnitVoltAmpereReactive",
"UnitAmpereHour"
"UnitAmpereHour",
"UnitMicroSiemensPerCentimeter",
"UnitDuration"
]
\endcode
\section2 UserError
@ -1492,12 +1508,13 @@ Returns
\code
{
"methods": "Object",
"notifications": "Object",
"types": "Object"
}
\endcode
\section2 JSONRPC.IsCloudConnected
Check whether the cloud is currently connected.
Check whether the cloud is currently connected. "connected" will be true whenever connectionState equals CloudConnectionStateConnected and is deprecated. Please use the connectionState value instead.
Params
\code
{}
@ -1505,10 +1522,11 @@ Params
Returns
\code
{
"connected": "Bool"
"connected": "Bool",
"connectionState": "$ref:CloudConnectionState"
}
\endcode
See also: \l{CloudConnectionState}
\section2 JSONRPC.KeepAlive
Keep alive a remote connection. The sessionId is the MQTT topic which has been used to establish the session. It will return false if no ongoing session with the given ID can be found.
Params
@ -1570,6 +1588,25 @@ Returns
}
\endcode
\section2 JSONRPC.SetupCloudConnection
Sets up the cloud connection by deploying a certificate and its configuration.
Params
\code
{
"certificatePEM": "String",
"endpoint": "String",
"privateKey": "String",
"publicKey": "String",
"rootCA": "String"
}
\endcode
Returns
\code
{
"success": "Bool"
}
\endcode
\section2 JSONRPC.SetupRemoteAccess
Setup the remote connection by providing AWS token information. This requires the cloud to be connected.
Params
@ -1617,7 +1654,15 @@ Returns
\endcode
\section2 Logging.GetLogEntries
Get the LogEntries matching the given filter. Each list element of a given filter will be connected with OR to each other. Each of the given filters will be connected with AND to each other.
Get the LogEntries matching the given filter. The result set will contain entries matching all filter rules combined. If multiple options are given for a single filter type, the result set will contain entries matching any of those. The offset starts at the newest entry in the result set. By default all items are returned. Example: If the specified filter returns a total amount of 100 entries:
- a offset value of 10 would include the oldest 90 entries
- a offset value of 0 would return all 100 entries
The offset is particularly useful in combination with the maxCount property and can be used for pagination. E.g. A result set of 10000 entries can be fetched in batches of 1000 entries by fetching
1) offset 0, maxCount 1000: Entries 0 to 9999
2) offset 10000, maxCount 1000: Entries 10000 - 19999
3) offset 20000, maxCount 1000: Entries 20000 - 29999
...
Params
\code
{
@ -1627,12 +1672,14 @@ Params
"o:eventTypes": [
"$ref:LoggingEventType"
],
"o:limit": "Int",
"o:loggingLevels": [
"$ref:LoggingLevel"
],
"o:loggingSources": [
"$ref:LoggingSource"
],
"o:offset": "Int",
"o:timeFilters": [
{
"o:endDate": "Int",
@ -1650,10 +1697,12 @@ Params
Returns
\code
{
"count": "Int",
"loggingError": "$ref:LoggingError",
"o:logEntries": [
"$ref:LogEntry"
]
],
"offset": "Int"
}
\endcode
See also: \l{LogEntry}, \l{LoggingError}, \l{LoggingLevel}, \l{LoggingEventType}, \l{LoggingSource}
@ -2768,14 +2817,16 @@ See also: \l{Tag}
"params": {},
"returns": {
"methods": "Object",
"notifications": "Object",
"types": "Object"
}
},
"JSONRPC.IsCloudConnected": {
"description": "Check whether the cloud is currently connected.",
"description": "Check whether the cloud is currently connected. \"connected\" will be true whenever connectionState equals CloudConnectionStateConnected and is deprecated. Please use the connectionState value instead.",
"params": {},
"returns": {
"connected": "Bool"
"connected": "Bool",
"connectionState": "$ref:CloudConnectionState"
}
},
"JSONRPC.KeepAlive": {
@ -2815,6 +2866,19 @@ See also: \l{Tag}
"enabled": "Bool"
}
},
"JSONRPC.SetupCloudConnection": {
"description": "Sets up the cloud connection by deploying a certificate and its configuration.",
"params": {
"certificatePEM": "String",
"endpoint": "String",
"privateKey": "String",
"publicKey": "String",
"rootCA": "String"
},
"returns": {
"success": "Bool"
}
},
"JSONRPC.SetupRemoteAccess": {
"description": "Setup the remote connection by providing AWS token information. This requires the cloud to be connected.",
"params": {
@ -2844,7 +2908,7 @@ See also: \l{Tag}
}
},
"Logging.GetLogEntries": {
"description": "Get the LogEntries matching the given filter. Each list element of a given filter will be connected with OR to each other. Each of the given filters will be connected with AND to each other.",
"description": "Get the LogEntries matching the given filter. The result set will contain entries matching all filter rules combined. If multiple options are given for a single filter type, the result set will contain entries matching any of those. The offset starts at the newest entry in the result set. By default all items are returned. Example: If the specified filter returns a total amount of 100 entries:\n- a offset value of 10 would include the oldest 90 entries\n- a offset value of 0 would return all 100 entries\n\nThe offset is particularly useful in combination with the maxCount property and can be used for pagination. E.g. A result set of 10000 entries can be fetched in batches of 1000 entries by fetching\n1) offset 0, maxCount 1000: Entries 0 to 9999\n2) offset 10000, maxCount 1000: Entries 10000 - 19999\n3) offset 20000, maxCount 1000: Entries 20000 - 29999\n...",
"params": {
"o:deviceIds": [
"Uuid"
@ -2852,12 +2916,14 @@ See also: \l{Tag}
"o:eventTypes": [
"$ref:LoggingEventType"
],
"o:limit": "Int",
"o:loggingLevels": [
"$ref:LoggingLevel"
],
"o:loggingSources": [
"$ref:LoggingSource"
],
"o:offset": "Int",
"o:timeFilters": [
{
"o:endDate": "Int",
@ -2872,10 +2938,12 @@ See also: \l{Tag}
]
},
"returns": {
"count": "Int",
"loggingError": "$ref:LoggingError",
"o:logEntries": [
"$ref:LogEntry"
]
],
"offset": "Int"
}
},
"NetworkManager.ConnectWifiNetwork": {
@ -3373,6 +3441,12 @@ See also: \l{Tag}
"o:repeating": "$ref:RepeatingOption",
"o:startTime": "Time"
},
"CloudConnectionState": [
"CloudConnectionStateDisabled",
"CloudConnectionStateUnconfigured",
"CloudConnectionStateConnecting",
"CloudConnectionStateConnected"
],
"ConfigurationError": [
"ConfigurationErrorNoError",
"ConfigurationErrorInvalidTimeZone",
@ -3798,7 +3872,12 @@ See also: \l{Tag}
"o:value": "String",
"tagId": "String"
},
"TagError": "$ref:TagError",
"TagError": [
"TagErrorNoError",
"TagErrorDeviceNotFound",
"TagErrorRuleNotFound",
"TagErrorTagNotFound"
],
"TimeDescriptor": {
"o:calendarItems": [
"$ref:CalendarItem"
@ -3868,7 +3947,9 @@ See also: \l{Tag}
"UnitMilliVolt",
"UnitVoltAmpere",
"UnitVoltAmpereReactive",
"UnitAmpereHour"
"UnitAmpereHour",
"UnitMicroSiemensPerCentimeter",
"UnitDuration"
],
"UserError": [
"UserErrorNoError",

View File

@ -1,16 +0,0 @@
#!/bin/sh
out_file=../../doc/interfacelist.qdoc
cur_dir=`pwd`
echo > $out_file
echo "\\list" >> $out_file
for i in `ls *.json`; do
echo "\\li \l{$i}" | sed s/\.json// >> $out_file
done
echo "\\endlist" >> $out_file
for i in `ls *.json`; do
echo "\\\target $i" | sed s/\.json// >> $out_file
echo "\\section2 $i" | sed s/\.json// >> $out_file
echo "\\quotefile $cur_dir/$i" >> $out_file
done

View File

@ -11,7 +11,7 @@ tests.depends = libnymea libnymea-core
doc.depends = FORCE
# Note: some how extraimages in qdocconf did not the trick
doc.commands += cd $$top_srcdir/libnymea/interfaces; ./generatedoc.sh;
doc.commands += cd $$top_srcdir/doc; ./generate-interfaces-qdoc.py;
doc.commands += cd $$top_srcdir/doc; ./generate-api-qdoc.py;
doc.commands += cd $$top_srcdir/doc; qdoc --highlighting config.qdocconf; cp -r images/* html/images/; \
cp -r favicons/* html/; cp -r $$top_srcdir/doc/html $$top_builddir/