diff --git a/README.md b/README.md index 27d3e73..707b279 100644 --- a/README.md +++ b/README.md @@ -48,12 +48,12 @@ |服务名称|服务说明|使用场景| |:------:|:------|:------| -|JT808.DotNetty.MsgIdHandler| 消息处理服务|从队列中消费设备上报数据,再结合自身的业务场景,将数据进行处理并入库 | -|JT808.DotNetty.MsgLogging | 消息日志服务|从队列中消费设备上报和平台应答数据,再将数据存入influxdb等数据库中,便于技术和技术支持排查设备与平台交互的原始数据| -|JT808.DotNetty.ReplyMessage| 消息响应服务| 用于响应设备上报消息,以及下发指令信息到设备| -|JT808.DotNetty.SessionNotice| 会话管理服务| 通知设备上线下线,对于udp设备来说,可以在设备上线时,将指令跟随消息下发到设备| -|JT808.DotNetty.Traffic|流量统计服务 |由于运营商sim卡查询流量滞后,通过流量统计服务可以实时准确的统计设备流量,可以最优配置设备的流量大小,以节省成本 -|JT808.DotNetty.Transmit| 原包转发服务|该服务可以将设备上报原始数据转发到第三方,支持全部转发,指定终端号转发| +|MsgIdHandler| 消息处理服务|从队列中消费设备上报数据,再结合自身的业务场景,将数据进行处理并入库 | +|MsgLogging | 消息日志服务|从队列中消费设备上报和平台应答数据,再将数据存入influxdb等数据库中,便于技术和技术支持排查设备与平台交互的原始数据| +|ReplyMessage| 消息响应服务| 用于响应设备上报消息,以及下发指令信息到设备| +|SessionNotice| 会话管理服务| 通知设备上线下线,对于udp设备来说,可以在设备上线时,将指令跟随消息下发到设备| +|Traffic|流量统计服务 |由于运营商sim卡查询流量滞后,通过流量统计服务可以实时准确的统计设备流量,可以最优配置设备的流量大小,以节省成本 +|Transmit| 原包转发服务|该服务可以将设备上报原始数据转发到第三方,支持全部转发,指定终端号转发| ## NuGet安装 diff --git a/src/JT808.Gateway.CleintBenchmark/Configs/ClientBenchmarkOptions.cs b/src/JT808.Gateway.CleintBenchmark/Configs/ClientBenchmarkOptions.cs new file mode 100644 index 0000000..f8dd628 --- /dev/null +++ b/src/JT808.Gateway.CleintBenchmark/Configs/ClientBenchmarkOptions.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.CleintBenchmark.Configs +{ + public class ClientBenchmarkOptions : IOptions + { + public string IP { get; set; } + public int Port { get; set; } + public int DeviceCount { get; set; } = 10; + /// + /// 5000ms毫秒 + /// + public int Interval { get; set; } = 5000; + public ClientBenchmarkOptions Value =>this; + } +} diff --git a/src/JT808.Gateway.CleintBenchmark/Configs/NLog.xsd b/src/JT808.Gateway.CleintBenchmark/Configs/NLog.xsd new file mode 100644 index 0000000..2f57d09 --- /dev/null +++ b/src/JT808.Gateway.CleintBenchmark/Configs/NLog.xsd @@ -0,0 +1,3106 @@ + + + + + + + + + + + + + + + Watch config file for changes and reload automatically. + + + + + Print internal NLog messages to the console. Default value is: false + + + + + Print internal NLog messages to the console error output. Default value is: false + + + + + Write internal NLog messages to the specified file. + + + + + Log level threshold for internal log messages. Default value is: Info. + + + + + Global log level threshold for application log messages. Messages below this level won't be logged.. + + + + + Throw an exception when there is an internal error. Default value is: false. + + + + + Throw an exception when there is a configuration error. If not set, determined by throwExceptions. + + + + + Gets or sets a value indicating whether Variables should be kept on configuration reload. Default value is: false. + + + + + Write internal NLog messages to the System.Diagnostics.Trace. Default value is: false. + + + + + Write timestamps for internal NLog messages. Default value is: true. + + + + + Use InvariantCulture as default culture instead of CurrentCulture. Default value is: false. + + + + + Perform mesage template parsing and formatting of LogEvent messages (true = Always, false = Never, empty = Auto Detect). Default value is: empty. + + + + + + + + + + + + + + Make all targets within this section asynchronous (creates additional threads but the calling thread isn't blocked by any target writes). + + + + + + + + + + + + + + + + + Prefix for targets/layout renderers/filters/conditions loaded from this assembly. + + + + + Load NLog extensions from the specified file (*.dll) + + + + + Load NLog extensions from the specified assembly. Assembly name should be fully qualified. + + + + + + + + + + Name of the logger. May include '*' character which acts like a wildcard. Allowed forms are: *, Name, *Name, Name* and *Name* + + + + + Comma separated list of levels that this rule matches. + + + + + Minimum level that this rule matches. + + + + + Maximum level that this rule matches. + + + + + Level that this rule matches. + + + + + Comma separated list of target names. + + + + + Ignore further rules if this one matches. + + + + + Enable or disable logging rule. Disabled rules are ignored. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the file to be included. You could use * wildcard. The name is relative to the name of the current config file. + + + + + Ignore any errors in the include file. + + + + + + + Variable name. + + + + + Variable value. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events that should be processed in a batch by the lazy writer thread. + + + + + Limit of full s to write before yielding into Performance is better when writing many small batches, than writing a single large batch + + + + + Action to be taken when the lazy writer thread request queue count exceeds the set limit. + + + + + Limit on the number of requests in the lazy writer thread request queue. + + + + + Time in milliseconds to sleep between batches. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Delay the flush until the LogEvent has been confirmed as written + + + + + Condition expression. Log events who meet this condition will cause a flush on the wrapped target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events to be buffered. + + + + + Timeout (in milliseconds) after which the contents of buffer will be flushed if there's no write in the specified period of time. Use -1 to disable timed flushes. + + + + + Indicates whether to use sliding timeout. + + + + + Action to take if the buffer overflows. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Maximum current connections. 0 = no maximum. + + + + + Indicates whether to keep connection open whenever possible. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Network address. + + + + + Maximum queue size. + + + + + NDC item separator. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + Option to include all properties from the log events + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout that should be use to calcuate the value for the parameter. + + + + + Viewer parameter name. + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to use default row highlighting rules. + + + + + Indicates whether to auto-check if the console is available. - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App) + + + + + The encoding for writing messages to the . + + + + + Indicates whether the error stream (stderr) should be used instead of the output stream (stdout). + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Condition that must be met in order to set the specified foreground and background color. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + Indicates whether to ignore case when comparing texts. + + + + + Regular expression to be matched. You must specify either text or regex. + + + + + Text to be matched. You must specify either text or regex. + + + + + Indicates whether to match whole words only. + + + + + Compile the ? This can improve the performance, but at the costs of more memory usage. If false, the Regex Cache is used. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to send the log messages to the standard error instead of the standard output. + + + + + Indicates whether to auto-check if the console is available - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App) + + + + + The encoding for writing messages to the . + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Obsolete - value will be ignored! The logging code always runs outside of transaction. Gets or sets a value indicating whether to use database transactions. Some data providers require this. + + + + + Database user name. If the ConnectionString is not provided this value will be used to construct the "User ID=" part of the connection string. + + + + + Name of the database provider. + + + + + Database password. If the ConnectionString is not provided this value will be used to construct the "Password=" part of the connection string. + + + + + Indicates whether to keep the database connection open between the log events. + + + + + Database name. If the ConnectionString is not provided this value will be used to construct the "Database=" part of the connection string. + + + + + Name of the connection string (as specified in <connectionStrings> configuration section. + + + + + Connection string. When provided, it overrides the values specified in DBHost, DBUserName, DBPassword, DBDatabase. + + + + + Database host name. If the ConnectionString is not provided this value will be used to construct the "Server=" part of the connection string. + + + + + Connection string using for installation and uninstallation. If not provided, regular ConnectionString is being used. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Text of the SQL command to be run on each log level. + + + + + Type of the SQL command to be run on each log level. + + + + + + + + + + + + + + + + + + + + + + + Type of the command. + + + + + Connection string to run the command against. If not provided, connection string from the target is used. + + + + + Indicates whether to ignore failures. + + + + + Command text. + + + + + + + + + + + + + + Layout that should be use to calcuate the value for the parameter. + + + + + Database parameter name. + + + + + Database parameter precision. + + + + + Database parameter scale. + + + + + Database parameter size. + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Layout that renders event Category. + + + + + Layout that renders event ID. + + + + + Name of the Event Log to write to. This can be System, Application or any user-defined name. + + + + + Name of the machine on which Event Log service is running. + + + + + Value to be used as the event Source. + + + + + Action to take if the message is larger than the option. + + + + + Optional entrytype. When not set, or when not convertable to then determined by + + + + + Maximum Event log size in kilobytes. If null, the value won't be set. Default is 512 Kilobytes as specified by Eventlog API + + + + + Message length limit to write to the Event Log. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether to return to the first target after any successful write. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + File encoding. + + + + + Line ending mode. + + + + + Way file archives are numbered. + + + + + Name of the file to be used for an archive. + + + + + Indicates whether to automatically archive log files every time the specified time passes. + + + + + Size in bytes above which log files will be automatically archived. Warning: combining this with isn't supported. We cannot create multiple archive files, if they should have the same name. Choose: + + + + + Indicates whether to compress archive files into the zip archive format. + + + + + Maximum number of archive files that should be kept. + + + + + Gets or set a value indicating whether a managed file stream is forced, instead of using the native implementation. + + + + + Is the an absolute or relative path? + + + + + Cleanup invalid values in a filename, e.g. slashes in a filename. If set to true, this can impact the performance of massive writes. If set to false, nothing gets written when the filename is wrong. + + + + + Whether or not this target should just discard all data that its asked to write. Mostly used for when testing NLog Stack except final write + + + + + Is the an absolute or relative path? + + + + + Value indicationg whether file creation calls should be synchronized by a system global mutex. + + + + + Maximum number of log filenames that should be stored as existing. + + + + + Indicates whether the footer should be written only when the file is archived. + + + + + Name of the file to write to. + + + + + Value specifying the date format to use when archiving files. + + + + + Indicates whether to archive old log file on startup. + + + + + Indicates whether to create directories if they do not exist. + + + + + File attributes (Windows only). + + + + + Indicates whether to delete old log file on startup. + + + + + Indicates whether to replace file contents on each write instead of appending log message at the end. + + + + + Indicates whether to enable log file(s) to be deleted. + + + + + Number of times the write is appended on the file before NLog discards the log message. + + + + + Indicates whether concurrent writes to the log file by multiple processes on the same host. + + + + + Indicates whether to keep log file open instead of opening and closing it on each logging event. + + + + + Indicates whether concurrent writes to the log file by multiple processes on different network hosts. + + + + + Number of files to be kept open. Setting this to a higher value may improve performance in a situation where a single File target is writing to many files (such as splitting by level or by logger). + + + + + Maximum number of seconds that files are kept open. If this number is negative the files are not automatically closed after a period of inactivity. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Log file buffer size in bytes. + + + + + Indicates whether to automatically flush the file buffers after each log message. + + + + + Delay in milliseconds to wait before attempting to write to the file again. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Condition expression. Log events who meet this condition will be forwarded to the wrapped target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Windows domain name to change context to. + + + + + Required impersonation level. + + + + + Type of the logon provider. + + + + + Logon Type. + + + + + User account password. + + + + + Indicates whether to revert to the credentials of the process instead of impersonating another user. + + + + + Username to change context to. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Interval in which messages will be written up to the number of messages. + + + + + Maximum allowed number of messages written per . + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Endpoint address. + + + + + Name of the endpoint configuration in WCF configuration file. + + + + + Indicates whether to use a WCF service contract that is one way (fire and forget) or two way (request-reply) + + + + + Client ID. + + + + + Indicates whether to include per-event properties in the payload sent to the server. + + + + + Indicates whether to use binary message encoding. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Layout that should be use to calculate the value for the parameter. + + + + + Name of the parameter. + + + + + Type of the parameter. + + + + + Type of the parameter. Obsolete alias for + + + + + Parameter can combine multiple LogEvents into a single parameter value + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to send message as HTML instead of plain text. + + + + + Encoding to be used for sending e-mail. + + + + + Indicates whether to add new lines between log entries. + + + + + CC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Recipients' email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + BCC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Mail message body (repeated for each log message send in one mail). + + + + + Mail subject. + + + + + Sender's email address (e.g. joe@domain.com). + + + + + Indicates the SMTP client timeout. + + + + + Priority used for sending mails. + + + + + Indicates whether NewLine characters in the body should be replaced with tags. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + SMTP Server to be used for sending. + + + + + SMTP Authentication mode. + + + + + Username used to connect to SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Password used to authenticate against SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Indicates whether SSL (secure sockets layer) should be used when communicating with SMTP server. + + + + + Port number that SMTP Server is listening on. + + + + + Indicates whether the default Settings from System.Net.MailSettings should be used. + + + + + Folder where applications save mail messages to be processed by the local SMTP server. + + + + + Specifies how outgoing email messages will be handled. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Class name. + + + + + Method name. The method must be public and static. Use the AssemblyQualifiedName , https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx e.g. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Encoding to be used. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Network address. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Indicates whether to keep connection open whenever possible. + + + + + Maximum current connections. 0 = no maximum. + + + + + Maximum queue size. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Maximum current connections. 0 = no maximum. + + + + + Indicates whether to keep connection open whenever possible. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Network address. + + + + + Maximum queue size. + + + + + NDC item separator. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + Option to include all properties from the log events + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Indicates whether to perform layout calculation. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether performance counter should be automatically created. + + + + + Name of the performance counter category. + + + + + Counter help text. + + + + + Name of the performance counter. + + + + + Performance counter type. + + + + + The value by which to increment the counter. + + + + + Performance counter instance name. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Default filter to be applied when no specific rule matches. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + Condition to be tested. + + + + + Resulting filter to be applied when the condition matches. + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Number of times to repeat each log message. + + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Number of retries that should be attempted on the wrapped target in case of a failure. + + + + + Time to wait between retries in milliseconds. + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Always use independent of + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Should we include the BOM (Byte-order-mark) for UTF? Influences the property. This will only work for UTF-8. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Encoding. + + + + + Value whether escaping be done according to the old NLog style (Very non-standard) + + + + + Value whether escaping be done according to Rfc3986 (Supports Internationalized Resource Identifiers - IRIs) + + + + + Web service method name. Only used with Soap. + + + + + Web service namespace. Only used with Soap. + + + + + Indicates whether to pre-authenticate the HttpWebRequest (Requires 'Authorization' in parameters) + + + + + Protocol to be used when calling web service. + + + + + Web service URL. + + + + + Name of the root XML element, if POST of XML document chosen. If so, this property must not be null. (see and ). + + + + + (optional) root namespace of the XML document, if POST of XML document chosen. (see and ). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + Custom column delimiter value (valid when ColumnDelimiter is set to 'Custom'). + + + + + Column delimiter. + + + + + Quote Character. + + + + + Quoting mode. + + + + + Indicates whether CVS should include header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout of the column. + + + + + Name of the column. + + + + + + + + + + + + + + + + + + List of property names to exclude when is true + + + + + Option to include all properties from the log events + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + Option to render the empty object value {} + + + + + Option to suppress the extra spaces in the output json + + + + + + + + + + + + + + + Determines wether or not this attribute will be Json encoded. + + + + + Indicates whether to escape non-ascii characters + + + + + Layout that will be rendered as the attribute's value. + + + + + Name of the attribute. + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + + + + + + + + + + + + + + Option to include all properties from the log events + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include contents of the stack. + + + + + + + + + + + + + + Layout text. + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Condition expression. + + + + + + + + + + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Layout to be used to filter log messages. + + + + + Default number of unique filter values to expect, will automatically increase if needed + + + + + Append FilterCount to the when an event is no longer filtered + + + + + Insert FilterCount value into when an event is no longer filtered + + + + + Applies the configured action to the initial logevent that starts the timeout period. Used to configure that it should ignore all events until timeout. + + + + + Max number of unique filter values to expect simultaneously + + + + + Max length of filter values, will truncate if above limit + + + + + Default buffer size for the internal buffers + + + + + Reuse internal buffers, and doesn't have to constantly allocate new buffers + + + + + How long before a filter expires, and logging is accepted again + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/JT808.Gateway.CleintBenchmark/Configs/nlog.unix.config b/src/JT808.Gateway.CleintBenchmark/Configs/nlog.unix.config new file mode 100644 index 0000000..2c8b777 --- /dev/null +++ b/src/JT808.Gateway.CleintBenchmark/Configs/nlog.unix.config @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/JT808.Gateway.CleintBenchmark/Configs/nlog.win.config b/src/JT808.Gateway.CleintBenchmark/Configs/nlog.win.config new file mode 100644 index 0000000..14d4a10 --- /dev/null +++ b/src/JT808.Gateway.CleintBenchmark/Configs/nlog.win.config @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/JT808.Gateway.CleintBenchmark/JT808.Gateway.CleintBenchmark.csproj b/src/JT808.Gateway.CleintBenchmark/JT808.Gateway.CleintBenchmark.csproj new file mode 100644 index 0000000..ad20926 --- /dev/null +++ b/src/JT808.Gateway.CleintBenchmark/JT808.Gateway.CleintBenchmark.csproj @@ -0,0 +1,33 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + + diff --git a/src/JT808.Gateway.CleintBenchmark/Program.cs b/src/JT808.Gateway.CleintBenchmark/Program.cs new file mode 100644 index 0000000..88451ca --- /dev/null +++ b/src/JT808.Gateway.CleintBenchmark/Program.cs @@ -0,0 +1,51 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using NLog.Extensions.Logging; +using System; +using System.Threading.Tasks; +using JT808.Protocol; +using Microsoft.Extensions.Configuration; +using JT808.Gateway.CleintBenchmark.Configs; +using JT808.Gateway.Client; +using JT808.Gateway.CleintBenchmark.Services; + +namespace JT808.Gateway.CleintBenchmark +{ + class Program + { + static async Task Main(string[] args) + { + var serverHostBuilder = new HostBuilder() + .ConfigureAppConfiguration((hostingContext, config) => + { + config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); + }) + .ConfigureLogging((context, logging) => + { + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + NLog.LogManager.LoadConfiguration("Configs/nlog.unix.config"); + } + else + { + NLog.LogManager.LoadConfiguration("Configs/nlog.win.config"); + } + logging.AddNLog(); + logging.SetMinimumLevel(LogLevel.Trace); + }) + .ConfigureServices((hostContext, services) => + { + services.Configure(hostContext.Configuration.GetSection("ClientBenchmarkOptions")); + services.AddSingleton(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddJT808Configure() + .AddJT808Client(); + services.AddHostedService(); + services.AddHostedService(); + }); + await serverHostBuilder.RunConsoleAsync(); + } + } +} diff --git a/src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkHostedService.cs b/src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkHostedService.cs new file mode 100644 index 0000000..8cfa879 --- /dev/null +++ b/src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkHostedService.cs @@ -0,0 +1,82 @@ +using JT808.Gateway.CleintBenchmark.Configs; +using JT808.Gateway.Client; +using JT808.Protocol.MessageBody; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + + +namespace JT808.Gateway.CleintBenchmark.Services +{ + public class CleintBenchmarkHostedService : IHostedService + { + private readonly ClientBenchmarkOptions clientBenchmarkOptions; + + private readonly ILogger logger; + + private readonly IJT808TcpClientFactory jT808TcpClientFactory; + + private CancellationTokenSource cts=new CancellationTokenSource(); + + private TaskFactory taskFactory; + + public CleintBenchmarkHostedService( + ILoggerFactory loggerFactory, + IJT808TcpClientFactory jT808TcpClientFactory, + IOptions clientBenchmarkOptionsAccessor) + { + this.jT808TcpClientFactory = jT808TcpClientFactory; + clientBenchmarkOptions = clientBenchmarkOptionsAccessor.Value; + logger = loggerFactory.CreateLogger("CleintBenchmarkHostedService"); + taskFactory = new TaskFactory(); + } + public Task StartAsync(CancellationToken cancellationToken) + { + logger.LogInformation("StartAsync..."); + ThreadPool.GetMinThreads(out var minWorkerThreads, out var minCompletionPortThreads); + ThreadPool.GetMaxThreads(out var maxWorkerThreads, out var maxCompletionPortThreads); + logger.LogInformation($"GetMinThreads:{minWorkerThreads}-{minCompletionPortThreads}"); + logger.LogInformation($"GetMaxThreads:{maxWorkerThreads}-{maxCompletionPortThreads}"); + //ThreadPool.SetMaxThreads(20, 20); + //ThreadPool.GetMaxThreads(out var setMaxWorkerThreads, out var setMaxCompletionPortThreads); + //logger.LogInformation($"SetMaxThreads:{setMaxWorkerThreads}-{setMaxCompletionPortThreads}"); + for (int i=0;i< clientBenchmarkOptions.DeviceCount; i++) + { + taskFactory.StartNew((item) => + { + var client = jT808TcpClientFactory.Create(new DeviceConfig(((int)item).ToString(), clientBenchmarkOptions.IP, clientBenchmarkOptions.Port)); + int lat = new Random(1000).Next(100000, 180000); + int Lng = new Random(1000).Next(100000, 180000); + while (!cts.IsCancellationRequested) + { + client.Send(new JT808_0x0200() + { + Lat = lat, + Lng = Lng, + GPSTime = DateTime.Now, + Speed = 50, + Direction = 30, + AlarmFlag = 5, + Altitude = 50, + StatusFlag = 10 + }); + Thread.Sleep(clientBenchmarkOptions.Interval); + } + }, i,cts.Token); + } + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + cts.Cancel(); + logger.LogInformation("StopAsync..."); + return Task.CompletedTask; + } + } +} diff --git a/src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkReportHostedService.cs b/src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkReportHostedService.cs new file mode 100644 index 0000000..768f475 --- /dev/null +++ b/src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkReportHostedService.cs @@ -0,0 +1,53 @@ +using JT808.Gateway.Services; +using JT808.Protocol.MessageBody; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + + +namespace JT808.Gateway.CleintBenchmark.Services +{ + public class CleintBenchmarkReportHostedService : IHostedService + { + private readonly JT808ClientReportService jT808ReportService; + + private CancellationTokenSource cts=new CancellationTokenSource(); + + private readonly ILogger logger; + public CleintBenchmarkReportHostedService( + ILoggerFactory loggerFactory, + JT808ClientReportService jT808ReportService) + { + this.jT808ReportService = jT808ReportService; + logger = loggerFactory.CreateLogger("CleintBenchmarkReportHostedService"); + } + public Task StartAsync(CancellationToken cancellationToken) + { + logger.LogInformation("StartAsync..."); + Task.Run(() => { + while (!cts.IsCancellationRequested) + { + logger.LogInformation(JsonConvert.SerializeObject(jT808ReportService.JT808Reports.LastOrDefault())); + Thread.Sleep(3000); + } + }, cts.Token); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + logger.LogInformation("StopAsync..."); + cts.Cancel(); + logger.LogInformation("正在生成报表..."); + logger.LogInformation(JsonConvert.SerializeObject(jT808ReportService.JT808Reports,Formatting.Indented)); + return Task.CompletedTask; + } + } +} diff --git a/src/JT808.Gateway.Kafka/Configs/JT808ConsumerConfig.cs b/src/JT808.Gateway.Kafka/Configs/JT808ConsumerConfig.cs new file mode 100644 index 0000000..9d2aa55 --- /dev/null +++ b/src/JT808.Gateway.Kafka/Configs/JT808ConsumerConfig.cs @@ -0,0 +1,15 @@ +using Confluent.Kafka; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.Configs.Kafka +{ + public class JT808ConsumerConfig: ConsumerConfig, IOptions + { + public string TopicName { get; set; } + + public JT808ConsumerConfig Value => this; + } +} diff --git a/src/JT808.Gateway.Kafka/Configs/JT808MsgConsumerConfig.cs b/src/JT808.Gateway.Kafka/Configs/JT808MsgConsumerConfig.cs new file mode 100644 index 0000000..53746e2 --- /dev/null +++ b/src/JT808.Gateway.Kafka/Configs/JT808MsgConsumerConfig.cs @@ -0,0 +1,13 @@ +using Confluent.Kafka; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.Configs.Kafka +{ + public class JT808MsgConsumerConfig : JT808ConsumerConfig, IOptions + { + JT808MsgConsumerConfig IOptions.Value => this; + } +} diff --git a/src/JT808.Gateway.Kafka/Configs/JT808MsgProducerConfig.cs b/src/JT808.Gateway.Kafka/Configs/JT808MsgProducerConfig.cs new file mode 100644 index 0000000..d55b2ce --- /dev/null +++ b/src/JT808.Gateway.Kafka/Configs/JT808MsgProducerConfig.cs @@ -0,0 +1,13 @@ +using Confluent.Kafka; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.Configs.Kafka +{ + public class JT808MsgProducerConfig : JT808ProducerConfig, IOptions + { + JT808MsgProducerConfig IOptions.Value => this; + } +} diff --git a/src/JT808.Gateway.Kafka/Configs/JT808MsgReplyConsumerConfig.cs b/src/JT808.Gateway.Kafka/Configs/JT808MsgReplyConsumerConfig.cs new file mode 100644 index 0000000..79f4c3c --- /dev/null +++ b/src/JT808.Gateway.Kafka/Configs/JT808MsgReplyConsumerConfig.cs @@ -0,0 +1,13 @@ +using Confluent.Kafka; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.Configs.Kafka +{ + public class JT808MsgReplyConsumerConfig : JT808ConsumerConfig, IOptions + { + JT808MsgReplyConsumerConfig IOptions.Value => this; + } +} diff --git a/src/JT808.Gateway.Kafka/Configs/JT808MsgReplyProducerConfig.cs b/src/JT808.Gateway.Kafka/Configs/JT808MsgReplyProducerConfig.cs new file mode 100644 index 0000000..9b62e6e --- /dev/null +++ b/src/JT808.Gateway.Kafka/Configs/JT808MsgReplyProducerConfig.cs @@ -0,0 +1,13 @@ +using Confluent.Kafka; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.Configs.Kafka +{ + public class JT808MsgReplyProducerConfig : JT808ProducerConfig, IOptions + { + JT808MsgReplyProducerConfig IOptions.Value => this; + } +} diff --git a/src/JT808.Gateway.Kafka/Configs/JT808ProducerConfig.cs b/src/JT808.Gateway.Kafka/Configs/JT808ProducerConfig.cs new file mode 100644 index 0000000..fca47cd --- /dev/null +++ b/src/JT808.Gateway.Kafka/Configs/JT808ProducerConfig.cs @@ -0,0 +1,15 @@ +using Confluent.Kafka; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.Configs.Kafka +{ + public class JT808ProducerConfig : ProducerConfig,IOptions + { + public string TopicName { get; set; } + + public JT808ProducerConfig Value => this; + } +} diff --git a/src/JT808.Gateway.Kafka/Configs/JT808SessionConsumerConfig.cs b/src/JT808.Gateway.Kafka/Configs/JT808SessionConsumerConfig.cs new file mode 100644 index 0000000..6b57a0a --- /dev/null +++ b/src/JT808.Gateway.Kafka/Configs/JT808SessionConsumerConfig.cs @@ -0,0 +1,13 @@ +using Confluent.Kafka; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.Configs.Kafka +{ + public class JT808SessionConsumerConfig : JT808ConsumerConfig, IOptions + { + JT808SessionConsumerConfig IOptions.Value => this; + } +} diff --git a/src/JT808.Gateway.Kafka/Configs/JT808SessionProducerConfig.cs b/src/JT808.Gateway.Kafka/Configs/JT808SessionProducerConfig.cs new file mode 100644 index 0000000..bba6871 --- /dev/null +++ b/src/JT808.Gateway.Kafka/Configs/JT808SessionProducerConfig.cs @@ -0,0 +1,13 @@ +using Confluent.Kafka; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.Configs.Kafka +{ + public class JT808SessionProducerConfig : JT808ProducerConfig, IOptions + { + JT808SessionProducerConfig IOptions.Value => this; + } +} diff --git a/src/JT808.Gateway.Kafka/JT808.Gateway.Kafka.csproj b/src/JT808.Gateway.Kafka/JT808.Gateway.Kafka.csproj new file mode 100644 index 0000000..f68e24b --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808.Gateway.Kafka.csproj @@ -0,0 +1,39 @@ + + + + netstandard2.0 + 8.0 + Copyright 2018. + SmallChi(Koike) + https://github.com/SmallChi/JT808DotNetty + https://github.com/SmallChi/JT808DotNetty + https://github.com/SmallChi/JT808DotNetty/blob/master/LICENSE + https://github.com/SmallChi/JT808DotNetty/blob/master/LICENSE + false + 1.0.0-preview1 + false + LICENSE + true + JT808.Gateway.Kafka + JT808.Gateway.Kafka + 基于Kafka的JT808消息发布与订阅 + 基于Kafka的JT808消息发布与订阅 + + + + + + + + + + + + + + + + + + + diff --git a/src/JT808.Gateway.Kafka/JT808ClientBuilderDefault.cs b/src/JT808.Gateway.Kafka/JT808ClientBuilderDefault.cs new file mode 100644 index 0000000..3279c64 --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808ClientBuilderDefault.cs @@ -0,0 +1,24 @@ +using JT808.Protocol; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.Kafka +{ + internal class JT808ClientBuilderDefault : IJT808ClientBuilder + { + public IJT808Builder JT808Builder { get; } + + public JT808ClientBuilderDefault(IJT808Builder builder) + { + JT808Builder = builder; + } + + public IJT808Builder Builder() + { + return JT808Builder; + } + } +} \ No newline at end of file diff --git a/src/JT808.Gateway.Kafka/JT808ClientKafkaExtensions.cs b/src/JT808.Gateway.Kafka/JT808ClientKafkaExtensions.cs new file mode 100644 index 0000000..b334097 --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808ClientKafkaExtensions.cs @@ -0,0 +1,66 @@ +using JJT808.Gateway.Kafka; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.PubSub; +using JT808.Protocol; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace JT808.Gateway.Kafka +{ + public static class JT808ClientKafkaExtensions + { + public static IJT808ClientBuilder AddJT808ClientKafka(this IJT808Builder builder) + { + return new JT808ClientBuilderDefault(builder); + } + /// + /// + /// + /// + /// GetSection("JT808MsgConsumerConfig") + /// + public static IJT808ClientBuilder AddMsgConsumer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) + { + jT808ClientBuilder.JT808Builder.Services.Configure(configuration.GetSection("JT808MsgConsumerConfig")); + jT808ClientBuilder.JT808Builder.Services.TryAddSingleton(); + return jT808ClientBuilder; + } + /// + /// + /// + /// + /// GetSection("JT808MsgReplyProducerConfig") + /// + public static IJT808ClientBuilder AddMsgReplyProducer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) + { + jT808ClientBuilder.JT808Builder.Services.Configure(configuration.GetSection("JT808MsgReplyProducerConfig")); + jT808ClientBuilder.JT808Builder.Services.TryAddSingleton(); + return jT808ClientBuilder; + } + /// + /// + /// + /// + /// GetSection("JT808MsgReplyConsumerConfig") + /// + public static IJT808ClientBuilder AddMsgReplyConsumer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) + { + jT808ClientBuilder.JT808Builder.Services.Configure(configuration.GetSection("JT808MsgReplyConsumerConfig")); + jT808ClientBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); + return jT808ClientBuilder; + } + /// + /// + /// + /// + /// GetSection("JT808SessionConsumerConfig") + /// + public static IJT808ClientBuilder AddSessionConsumer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) + { + jT808ClientBuilder.JT808Builder.Services.Configure(configuration.GetSection("JT808SessionConsumerConfig")); + jT808ClientBuilder.JT808Builder.Services.TryAddSingleton(); + return jT808ClientBuilder; + } + } +} \ No newline at end of file diff --git a/src/JT808.Gateway.Kafka/JT808MsgConsumer.cs b/src/JT808.Gateway.Kafka/JT808MsgConsumer.cs new file mode 100644 index 0000000..56818f2 --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808MsgConsumer.cs @@ -0,0 +1,82 @@ +using Confluent.Kafka; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.PubSub; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace JT808.Gateway.Kafka +{ + public class JT808MsgConsumer : IJT808MsgConsumer + { + public CancellationTokenSource Cts => new CancellationTokenSource(); + + private readonly IConsumer consumer; + + private readonly ILogger logger; + + public string TopicName { get; } + + public JT808MsgConsumer( + IOptions consumerConfigAccessor, + ILoggerFactory loggerFactory) + { + consumer = new ConsumerBuilder(consumerConfigAccessor.Value).Build(); + TopicName = consumerConfigAccessor.Value.TopicName; + logger = loggerFactory.CreateLogger("JT808MsgConsumer"); + } + + public void OnMessage(Action<(string TerminalNo, byte[] Data)> callback) + { + Task.Run(() => + { + while (!Cts.IsCancellationRequested) + { + try + { + //如果不指定分区,根据kafka的机制会从多个分区中拉取数据 + //如果指定分区,根据kafka的机制会从相应的分区中拉取数据 + var data = consumer.Consume(Cts.Token); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug($"Topic: {data.Topic} Key: {data.Key} Partition: {data.Partition} Offset: {data.Offset} TopicPartitionOffset:{data.TopicPartitionOffset}"); + } + callback((data.Key, data.Value)); + } + catch (ConsumeException ex) + { + logger.LogError(ex, TopicName); + } + catch (OperationCanceledException ex) + { + logger.LogError(ex, TopicName); + } + catch (Exception ex) + { + logger.LogError(ex, TopicName); + } + } + }, Cts.Token); + } + + public void Subscribe() + { + consumer.Subscribe(TopicName); + } + + public void Unsubscribe() + { + consumer.Unsubscribe(); + } + + public void Dispose() + { + consumer.Close(); + consumer.Dispose(); + } + } +} diff --git a/src/JT808.Gateway.Kafka/JT808MsgProducer.cs b/src/JT808.Gateway.Kafka/JT808MsgProducer.cs new file mode 100644 index 0000000..67d6d1b --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808MsgProducer.cs @@ -0,0 +1,38 @@ +using Confluent.Kafka; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.PubSub; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace JT808.Gateway.Kafka +{ + public class JT808MsgProducer : IJT808MsgProducer + { + public string TopicName { get; } + + private readonly IProducer producer; + public JT808MsgProducer( + IOptions producerConfigAccessor) + { + producer = new ProducerBuilder(producerConfigAccessor.Value).Build(); + TopicName = producerConfigAccessor.Value.TopicName; + } + + public void Dispose() + { + producer.Dispose(); + } + + public async Task ProduceAsync(string terminalNo, byte[] data) + { + await producer.ProduceAsync(TopicName, new Message + { + Key = terminalNo, + Value = data + }); + } + } +} diff --git a/src/JT808.Gateway.Kafka/JT808MsgReplyConsumer.cs b/src/JT808.Gateway.Kafka/JT808MsgReplyConsumer.cs new file mode 100644 index 0000000..004a391 --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808MsgReplyConsumer.cs @@ -0,0 +1,82 @@ +using Confluent.Kafka; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.PubSub; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace JT808.Gateway.Kafka +{ + public class JT808MsgReplyConsumer : IJT808MsgReplyConsumer + { + public CancellationTokenSource Cts => new CancellationTokenSource(); + + private readonly IConsumer consumer; + + private readonly ILogger logger; + + public string TopicName { get; } + + public JT808MsgReplyConsumer( + IOptions consumerConfigAccessor, + ILoggerFactory loggerFactory) + { + consumer = new ConsumerBuilder(consumerConfigAccessor.Value).Build(); + TopicName = consumerConfigAccessor.Value.TopicName; + logger = loggerFactory.CreateLogger("JT808MsgReplyConsumer"); + } + + public void OnMessage(Action<(string TerminalNo, byte[] Data)> callback) + { + Task.Run(() => + { + while (!Cts.IsCancellationRequested) + { + try + { + //如果不指定分区,根据kafka的机制会从多个分区中拉取数据 + //如果指定分区,根据kafka的机制会从相应的分区中拉取数据 + var data = consumer.Consume(Cts.Token); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug($"Topic: {data.Topic} Key: {data.Key} Partition: {data.Partition} Offset: {data.Offset} TopicPartitionOffset:{data.TopicPartitionOffset}"); + } + callback((data.Key, data.Value)); + } + catch (ConsumeException ex) + { + logger.LogError(ex, TopicName); + } + catch (OperationCanceledException ex) + { + logger.LogError(ex, TopicName); + } + catch (Exception ex) + { + logger.LogError(ex, TopicName); + } + } + }, Cts.Token); + } + + public void Subscribe() + { + consumer.Subscribe(TopicName); + } + + public void Unsubscribe() + { + consumer.Unsubscribe(); + } + + public void Dispose() + { + consumer.Close(); + consumer.Dispose(); + } + } +} diff --git a/src/JT808.Gateway.Kafka/JT808MsgReplyProducer.cs b/src/JT808.Gateway.Kafka/JT808MsgReplyProducer.cs new file mode 100644 index 0000000..f29e9be --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808MsgReplyProducer.cs @@ -0,0 +1,38 @@ +using Confluent.Kafka; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.PubSub; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace JJT808.Gateway.Kafka +{ + public class JT808MsgReplyProducer : IJT808MsgReplyProducer + { + public string TopicName { get;} + + private IProducer producer; + public JT808MsgReplyProducer( + IOptions producerConfigAccessor) + { + producer = new ProducerBuilder(producerConfigAccessor.Value).Build(); + TopicName = producerConfigAccessor.Value.TopicName; + } + + public void Dispose() + { + producer.Dispose(); + } + + public async Task ProduceAsync(string terminalNo, byte[] data) + { + await producer.ProduceAsync(TopicName, new Message + { + Key = terminalNo, + Value = data + }); + } + } +} diff --git a/src/JT808.Gateway.Kafka/JT808ServerKafkaExtensions.cs b/src/JT808.Gateway.Kafka/JT808ServerKafkaExtensions.cs new file mode 100644 index 0000000..e8e1dc1 --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808ServerKafkaExtensions.cs @@ -0,0 +1,48 @@ +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.PubSub; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace JT808.Gateway.Kafka +{ + public static class JT808ServerKafkaExtensions + { + /// + /// + /// + /// + /// GetSection("JT808MsgProducerConfig") + /// + public static IJT808GatewayBuilder AddJT808ServerKafkaMsgProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) + { + jT808GatewayBuilder.JT808Builder.Services.Configure(configuration.GetSection("JT808MsgProducerConfig")); + jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgProducer), typeof(JT808MsgProducer), ServiceLifetime.Singleton)); + return jT808GatewayBuilder; + } + /// + /// + /// + /// + /// GetSection("JT808MsgReplyConsumerConfig") + /// + public static IJT808GatewayBuilder AddJT808ServerKafkaMsgReplyConsumer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) + { + jT808GatewayBuilder.JT808Builder.Services.Configure(configuration.GetSection("JT808MsgReplyConsumerConfig")); + jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); + return jT808GatewayBuilder; + } + /// + /// + /// + /// + /// GetSection("JT808SessionProducerConfig") + /// + public static IJT808GatewayBuilder AddJT808ServerKafkaSessionProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) + { + jT808GatewayBuilder.JT808Builder.Services.Configure(configuration.GetSection("JT808SessionProducerConfig")); + jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808SessionProducer), typeof(JT808SessionProducer), ServiceLifetime.Singleton)); + return jT808GatewayBuilder; + } + } +} \ No newline at end of file diff --git a/src/JT808.Gateway.Kafka/JT808SessionConsumer.cs b/src/JT808.Gateway.Kafka/JT808SessionConsumer.cs new file mode 100644 index 0000000..9ccf830 --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808SessionConsumer.cs @@ -0,0 +1,82 @@ +using Confluent.Kafka; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.PubSub; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace JT808.Gateway.Kafka +{ + public class JT808SessionConsumer : IJT808SessionConsumer + { + public CancellationTokenSource Cts => new CancellationTokenSource(); + + private readonly IConsumer consumer; + + private readonly ILogger logger; + + public string TopicName { get; } + + public JT808SessionConsumer( + IOptions consumerConfigAccessor, + ILoggerFactory loggerFactory) + { + consumer = new ConsumerBuilder(consumerConfigAccessor.Value).Build(); + TopicName = consumerConfigAccessor.Value.TopicName; + logger = loggerFactory.CreateLogger("JT808SessionConsumer"); + } + + public void OnMessage(Action<(string Notice, string TerminalNo)> callback) + { + Task.Run(() => + { + while (!Cts.IsCancellationRequested) + { + try + { + //如果不指定分区,根据kafka的机制会从多个分区中拉取数据 + //如果指定分区,根据kafka的机制会从相应的分区中拉取数据 + var data = consumer.Consume(Cts.Token); + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug($"Topic: {data.Topic} Key: {data.Key} Partition: {data.Partition} Offset: {data.Offset} TopicPartitionOffset:{data.TopicPartitionOffset}"); + } + callback((data.Key, data.Value)); + } + catch (ConsumeException ex) + { + logger.LogError(ex, TopicName); + } + catch (OperationCanceledException ex) + { + logger.LogError(ex, TopicName); + } + catch (Exception ex) + { + logger.LogError(ex, TopicName); + } + } + }, Cts.Token); + } + + public void Subscribe() + { + consumer.Subscribe(TopicName); + } + + public void Unsubscribe() + { + consumer.Unsubscribe(); + } + + public void Dispose() + { + consumer.Close(); + consumer.Dispose(); + } + } +} diff --git a/src/JT808.Gateway.Kafka/JT808SessionProducer.cs b/src/JT808.Gateway.Kafka/JT808SessionProducer.cs new file mode 100644 index 0000000..3b6494f --- /dev/null +++ b/src/JT808.Gateway.Kafka/JT808SessionProducer.cs @@ -0,0 +1,38 @@ +using Confluent.Kafka; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.PubSub; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace JT808.Gateway.Kafka +{ + public class JT808SessionProducer : IJT808SessionProducer + { + public string TopicName { get; } + + private readonly IProducer producer; + public JT808SessionProducer( + IOptions producerConfigAccessor) + { + producer = new ProducerBuilder(producerConfigAccessor.Value).Build(); + TopicName = producerConfigAccessor.Value.TopicName; + } + + public void Dispose() + { + producer.Dispose(); + } + + public async Task ProduceAsync(string notice,string terminalNo) + { + await producer.ProduceAsync(TopicName, new Message + { + Key = notice, + Value = terminalNo + }); + } + } +} diff --git a/src/JT808.Gateway.SimpleClient/Program.cs b/src/JT808.Gateway.SimpleClient/Program.cs index e7158bb..1e0452d 100644 --- a/src/JT808.Gateway.SimpleClient/Program.cs +++ b/src/JT808.Gateway.SimpleClient/Program.cs @@ -8,6 +8,7 @@ using System; using System.Threading.Tasks; using Grpc.Net.Client; using JT808.Gateway.GrpcService; +using System.Net; namespace JT808.Gateway.SimpleClient { @@ -16,7 +17,12 @@ namespace JT808.Gateway.SimpleClient static async Task Main(string[] args) { //ref https://docs.microsoft.com/zh-cn/aspnet/core/grpc/troubleshoot?view=aspnetcore-3.0#call-insecure-grpc-services-with-net-core-client - AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); + //ref https://docs.microsoft.com/zh-cn/aspnet/core/grpc/troubleshoot?view=aspnetcore-3.0 + + //先执行 dotnet dev-certs https --trust 命令生成开发证书 + //使用 certmgr.msc 导出证书在服务端配置对应证书文件 + //Uri "https://localhost:5001" + var serverHostBuilder = new HostBuilder() .ConfigureLogging((context, logging) => { @@ -27,7 +33,7 @@ namespace JT808.Gateway.SimpleClient { services.AddGrpcClient(o => { - o.Address = new Uri("https://127.0.0.1:5001"); + o.Address = new Uri("https://localhost:5001"); }); services.AddSingleton(); services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); diff --git a/src/JT808.Gateway.SimpleClient/Services/GrpcClientService.cs b/src/JT808.Gateway.SimpleClient/Services/GrpcClientService.cs index b04b1e8..e21a3dc 100644 --- a/src/JT808.Gateway.SimpleClient/Services/GrpcClientService.cs +++ b/src/JT808.Gateway.SimpleClient/Services/GrpcClientService.cs @@ -32,8 +32,8 @@ namespace JT808.Gateway.SimpleClient.Services public Task StartAsync(CancellationToken cancellationToken) { Task.Run(() => { - while (!cancellationToken.IsCancellationRequested) - { + //while (!cancellationToken.IsCancellationRequested) + //{ Thread.Sleep(1000 * 10); var result1 = client.GetTcpAtomicCounter(new Empty()); var result2 = client.GetUdpAtomicCounter(new Empty()); @@ -55,7 +55,7 @@ namespace JT808.Gateway.SimpleClient.Services logger.LogDebug(JsonSerializer.Serialize(result4)); logger.LogDebug(JsonSerializer.Serialize(result5)); logger.LogDebug(JsonSerializer.Serialize(result6)); - } + //} }, cancellationToken); return Task.CompletedTask; } diff --git a/src/JT808.Gateway.SimpleServer/Configs/test.cer b/src/JT808.Gateway.SimpleServer/Configs/test.cer new file mode 100644 index 0000000..04963c1 Binary files /dev/null and b/src/JT808.Gateway.SimpleServer/Configs/test.cer differ diff --git a/src/JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj b/src/JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj index 55c13a6..d8666d6 100644 --- a/src/JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj +++ b/src/JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj @@ -30,6 +30,9 @@ Always + + Always + diff --git a/src/JT808.Gateway.SimpleServer/Program.cs b/src/JT808.Gateway.SimpleServer/Program.cs index 25ecb19..2590e7f 100644 --- a/src/JT808.Gateway.SimpleServer/Program.cs +++ b/src/JT808.Gateway.SimpleServer/Program.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; using System; +using System.IO; using System.Net; namespace JT808.Gateway.SimpleServer @@ -31,17 +32,17 @@ namespace JT808.Gateway.SimpleServer configLogging.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true }); configLogging.SetMinimumLevel(LogLevel.Trace); }) - .ConfigureWebHostDefaults(webBuilder => { webBuilder - //.ConfigureKestrel(options => - //{ - // options.Listen(IPAddress.Any, 5001, listenOptions => - // { - // listenOptions.Protocols = HttpProtocols.Http2; - // }); - //}) + .ConfigureKestrel(options => + { + options.Listen(IPAddress.Any, 5001, listenOptions => + { + listenOptions.Protocols = HttpProtocols.Http2; + listenOptions.UseHttps($"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs", "test.cer")}", ""); + }); + }) .Configure(app => { app.UseRouting(); @@ -53,7 +54,7 @@ namespace JT808.Gateway.SimpleServer }) .ConfigureServices((hostContext,services) => { - services.Configure(hostContext.Configuration.GetSection("Kestrel")); + //services.Configure(hostContext.Configuration.GetSection("Kestrel")); services.AddGrpc(); services.AddSingleton(); services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.MsgIdHandler.Test/JT808.Gateway.MsgIdHandler.Test.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.MsgIdHandler.Test/JT808.Gateway.MsgIdHandler.Test.csproj new file mode 100644 index 0000000..7c471ef --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.MsgIdHandler.Test/JT808.Gateway.MsgIdHandler.Test.csproj @@ -0,0 +1,24 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + + Always + + + + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.MsgIdHandler.Test/JT808DotNettyMsgIdHandlerDefaultImpl.cs b/src/JT808.Gateway.Tests/JT808.Gateway.MsgIdHandler.Test/JT808DotNettyMsgIdHandlerDefaultImpl.cs new file mode 100644 index 0000000..58ad123 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.MsgIdHandler.Test/JT808DotNettyMsgIdHandlerDefaultImpl.cs @@ -0,0 +1,44 @@ +using JT808.Gateway.BusinessServices.MsgIdHandler; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.Kafka; +using JT808.Gateway.PubSub; +using JT808.Protocol; +using JT808.Protocol.Extensions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace JT808.Gateway.MsgIdHandler.Test +{ + public class JT808DotNettyMsgIdHandlerDefaultImpl : IJT808MsgIdHandler + { + public readonly ILogger logger; + public JT808DotNettyMsgIdHandlerDefaultImpl(ILoggerFactory loggerFactory, + IServiceProvider serviceProvider) { + logger = loggerFactory.CreateLogger(); + Task.Run(()=> { + while (true) + { + Thread.Sleep(5000); + using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig + { + BootstrapServers = "127.0.0.1:9092", + TopicName = "JT808Msg" + })) + { + jT808MsgProducer.ProduceAsync("123456", new byte[] { 0x7E, 0, 0x7E }).Wait(); + } + } + }); + } + + public void Processor((string TerminalNo, byte[] Data) parameter) + { + logger.LogDebug($"{parameter.TerminalNo}:{parameter.Data.ToHexString()}"); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.MsgIdHandler.Test/Program.cs b/src/JT808.Gateway.Tests/JT808.Gateway.MsgIdHandler.Test/Program.cs new file mode 100644 index 0000000..f96f9cd --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.MsgIdHandler.Test/Program.cs @@ -0,0 +1,39 @@ +using JT808.Gateway.BusinessServices.MsgIdHandler; +using JT808.Gateway.Kafka; +using JT808.Protocol; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Threading.Tasks; + +namespace JT808.Gateway.MsgIdHandler.Test +{ + class Program + { + async static Task Main(string[] args) + { + var serverHostBuilder = new HostBuilder() + .UseEnvironment(args[0].Split('=')[1]) + .ConfigureAppConfiguration((hostingContext,config) => { + config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{ hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); + }) + .ConfigureLogging(configLogging => { + configLogging.AddConsole(); + configLogging.SetMinimumLevel(LogLevel.Trace); + }) + .ConfigureServices((hostContext, services) => { + services.AddSingleton(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddJT808Configure() + .AddJT808ClientKafka() + .AddMsgConsumer(hostContext.Configuration) + .AddJT808MsgIdHandler(); + }); + await serverHostBuilder.RunConsoleAsync(); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.MsgLogging.Test/JT808.Gateway.MsgLogging.Test.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.MsgLogging.Test/JT808.Gateway.MsgLogging.Test.csproj new file mode 100644 index 0000000..13142a7 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.MsgLogging.Test/JT808.Gateway.MsgLogging.Test.csproj @@ -0,0 +1,25 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + + + Always + + + + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.MsgLogging.Test/JT808MsgLoggingImpl.cs b/src/JT808.Gateway.Tests/JT808.Gateway.MsgLogging.Test/JT808MsgLoggingImpl.cs new file mode 100644 index 0000000..033b8f1 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.MsgLogging.Test/JT808MsgLoggingImpl.cs @@ -0,0 +1,52 @@ +using JJT808.Gateway.Kafka; +using JT808.Gateway.BusinessServices.MsgLogging; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.Kafka; +using JT808.Gateway.PubSub; +using JT808.Protocol.Extensions; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace JT808.Gateway.MsgLogging.Test +{ + public class JT808MsgLoggingImpl : IJT808MsgLogging + { + public readonly ILogger logger; + public JT808MsgLoggingImpl(ILoggerFactory loggerFactory) { + logger = loggerFactory.CreateLogger(); + Task.Run(() => { + while (true) + { + Thread.Sleep(5000); + using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig + { + BootstrapServers = "127.0.0.1:9092", + TopicName = "JT808Msg" + })) + { + jT808MsgProducer.ProduceAsync("123456", new byte[] { 0x7E, 0,0,0,0, 0x7E }).Wait(); + } + + JT808MsgReplyProducerConfig JT808MsgProducerConfig = new JT808MsgReplyProducerConfig + { + TopicName = "JT808MsgReply", + BootstrapServers = "127.0.0.1:9092", + }; + using (IJT808MsgReplyProducer jT808MsgProducer = new JT808MsgReplyProducer(JT808MsgProducerConfig)) + { + jT808MsgProducer.ProduceAsync("123456", new byte[] { 0x7E,1,1,1,1, 0x7E }).Wait(); + } + } + }); + } + + public void Processor((string TerminalNo, byte[] Data) parameter, JT808MsgLoggingType jT808MsgLoggingType) + { + logger.LogDebug($"{parameter.TerminalNo}:{parameter.Data.ToHexString()},方向:{jT808MsgLoggingType.ToString()}"); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.MsgLogging.Test/Program.cs b/src/JT808.Gateway.Tests/JT808.Gateway.MsgLogging.Test/Program.cs new file mode 100644 index 0000000..482e60f --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.MsgLogging.Test/Program.cs @@ -0,0 +1,43 @@ +using JT808.Gateway.BusinessServices.MsgLogging; +using JT808.Gateway.Kafka; +using JT808.Protocol; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Console; +using System; +using System.Threading.Tasks; + +namespace JT808.Gateway.MsgLogging.Test +{ + class Program + { + async static Task Main(string[] args) + { + var hostBuilder = new HostBuilder() + .UseEnvironment(args[0].Split('=')[1]) + .ConfigureAppConfiguration((hostContext,config)=> { + config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); + }) + .ConfigureLogging((hostContext, configLogging) => { + configLogging.AddConsole(); + configLogging.SetMinimumLevel(LogLevel.Trace); + }) + .ConfigureServices((hostContext, services) => { + services.AddSingleton(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddJT808Configure() + .AddJT808ClientKafka() + .AddMsgConsumer(hostContext.Configuration) + .AddMsgReplyConsumer(hostContext.Configuration) + .AddJT808MsgLogging(); + }) + ; + + await hostBuilder.RunConsoleAsync(); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.ReplyMessage.Test/JT808.Gateway.ReplyMessage.Test.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.ReplyMessage.Test/JT808.Gateway.ReplyMessage.Test.csproj new file mode 100644 index 0000000..da55908 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.ReplyMessage.Test/JT808.Gateway.ReplyMessage.Test.csproj @@ -0,0 +1,25 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + + + Always + + + + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.ReplyMessage.Test/JT808DotNettyReplyMessageServiceInherited.cs b/src/JT808.Gateway.Tests/JT808.Gateway.ReplyMessage.Test/JT808DotNettyReplyMessageServiceInherited.cs new file mode 100644 index 0000000..4f400a8 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.ReplyMessage.Test/JT808DotNettyReplyMessageServiceInherited.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using JT808.Gateway.BusinessServices.ReplyMessage; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.Kafka; +using JT808.Gateway.PubSub; +using JT808.Protocol; +using JT808.Protocol.Extensions; +using Microsoft.Extensions.Logging; + +namespace JT808.Gateway.ReplyMessage.Test +{ + public class JT808DotNettyReplyMessageServiceInherited : JT808ReplyMessageService + { + public readonly ILogger logger; + + public JT808DotNettyReplyMessageServiceInherited(IJT808Config jT808Config, + IJT808MsgReplyProducer jT808MsgReplyProducer, + ILoggerFactory loggerFactory) + : base(jT808Config, jT808MsgReplyProducer) + { + logger = loggerFactory.CreateLogger(); + Task.Run(() => { + while (true) + { + Thread.Sleep(5000); + using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig + { + BootstrapServers = "127.0.0.1:9092", + TopicName = "JT808Msg" + })) + { + jT808MsgProducer.ProduceAsync("011111111111", "7E02000032011111111111012E00000000000C00000160E42506C30C82002C00000000180914142057010400001DC003020000250400000000300115310100977E".ToHexBytes()).Wait(); + } + } + }); + } + + public override void Processor((string TerminalNo, byte[] Data) parameter) + { + logger.LogDebug($"{parameter.TerminalNo}:{parameter.Data.ToHexString()}"); + base.Processor(parameter); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.ReplyMessage.Test/Program.cs b/src/JT808.Gateway.Tests/JT808.Gateway.ReplyMessage.Test/Program.cs new file mode 100644 index 0000000..eafa6a0 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.ReplyMessage.Test/Program.cs @@ -0,0 +1,42 @@ +using JT808.Gateway.BusinessServices.ReplyMessage; +using JT808.Gateway.Kafka; +using JT808.Protocol; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Threading.Tasks; + +namespace JT808.Gateway.ReplyMessage.Test +{ + class Program + { + async static Task Main(string[] args) + { + var hostBuilder = new HostBuilder() + .UseEnvironment(args[0].Split('=')[1]) + .ConfigureAppConfiguration((hostContext, config) => { + config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); + }) + .ConfigureLogging((hostContext, configLogging) => { + configLogging.AddConsole(); + configLogging.SetMinimumLevel(LogLevel.Trace); + }) + .ConfigureServices((hostContext, services) => { + services.AddSingleton(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddJT808Configure() + .AddJT808ClientKafka() + .AddMsgConsumer(hostContext.Configuration) + .AddMsgReplyProducer(hostContext.Configuration) + .AddInprocJT808ReplyMessage(); + }) + ; + + await hostBuilder.RunConsoleAsync(); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.SessionNotice.Test/JT808.Gateway.SessionNotice.Test.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.SessionNotice.Test/JT808.Gateway.SessionNotice.Test.csproj new file mode 100644 index 0000000..c6b1507 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.SessionNotice.Test/JT808.Gateway.SessionNotice.Test.csproj @@ -0,0 +1,24 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + + Always + + + + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.SessionNotice.Test/JT808DotNettySessionNoticeServiceInherited.cs b/src/JT808.Gateway.Tests/JT808.Gateway.SessionNotice.Test/JT808DotNettySessionNoticeServiceInherited.cs new file mode 100644 index 0000000..2c846c2 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.SessionNotice.Test/JT808DotNettySessionNoticeServiceInherited.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using JT808.Gateway.BusinessServices.SessionNotice; +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.Kafka; +using JT808.Gateway.PubSub; +using Microsoft.Extensions.Logging; + +namespace JT808.Gateway.SessionNotice.Test +{ + public class JT808DotNettySessionNoticeServiceInherited : JT808SessionNoticeService + { + public JT808DotNettySessionNoticeServiceInherited(ILoggerFactory loggerFactory) : base(loggerFactory) + { + Task.Run(()=> { + while (true) + { + Thread.Sleep(5000); + JT808SessionProducerConfig JT808ProducerConfig = new JT808SessionProducerConfig + { + TopicName = "JT808Session", + BootstrapServers = "127.0.0.1:9092" + }; + using (IJT808SessionProducer jT808MsgProducer = new JT808SessionProducer(JT808ProducerConfig)) + { + jT808MsgProducer.ProduceAsync("online", "123456").Wait(); + jT808MsgProducer.ProduceAsync("offline", "123457").Wait(); + } + } + }); + } + + public override void Processor((string Notice, string TerminalNo) parameter) + { + base.Processor(parameter); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.SessionNotice.Test/Program.cs b/src/JT808.Gateway.Tests/JT808.Gateway.SessionNotice.Test/Program.cs new file mode 100644 index 0000000..24196a6 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.SessionNotice.Test/Program.cs @@ -0,0 +1,41 @@ +using JT808.Gateway.BusinessServices.SessionNotice; +using JT808.Gateway.Kafka; +using JT808.Protocol; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Threading.Tasks; + +namespace JT808.Gateway.SessionNotice.Test +{ + class Program + { + async static Task Main(string[] args) + { + var hostBuilder = new HostBuilder() + .UseEnvironment(args[0].Split('=')[1]) + .ConfigureAppConfiguration((hostContext, config) => { + config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); + }) + .ConfigureLogging((hostContext, configLogging) => { + configLogging.AddConsole(); + configLogging.SetMinimumLevel(LogLevel.Trace); + }) + .ConfigureServices((hostContext, services) => { + services.AddSingleton(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddJT808Configure() + .AddJT808ClientKafka() + .AddSessionConsumer(hostContext.Configuration) + .AddInprocJT808SessionNotice(); + }) + ; + + await hostBuilder.RunConsoleAsync(); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj new file mode 100644 index 0000000..7745168 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj @@ -0,0 +1,32 @@ + + + + netcoreapp3.0 + + false + + + + + + + + + + + + + + + + + + + Always + + + Always + + + + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/Tcp/JT808SessionServiceTest.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Tcp/JT808SessionServiceTest.cs new file mode 100644 index 0000000..0339c36 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Tcp/JT808SessionServiceTest.cs @@ -0,0 +1,94 @@ +using JT808.Protocol; +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; +using System.Threading; +using Microsoft.Extensions.DependencyInjection; +using JT808.Protocol.Extensions; +using Xunit; +using JT808.Gateway.Interfaces; +using JT808.Gateway.Session; +using JT808.Gateway.Simples; + +namespace JT808.Gateway.Test.Tcp +{ + public class JT808SessionServiceTest:TestBase,IDisposable + { + static IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565); + + JT808SimpleTcpClient SimpleTcpClient1; + JT808SimpleTcpClient SimpleTcpClient2; + JT808SimpleTcpClient SimpleTcpClient3; + JT808SimpleTcpClient SimpleTcpClient4; + JT808SimpleTcpClient SimpleTcpClient5; + + public JT808SessionServiceTest() + { + SimpleTcpClient1 = new JT808SimpleTcpClient(endPoint); + SimpleTcpClient2 = new JT808SimpleTcpClient(endPoint); + SimpleTcpClient3 = new JT808SimpleTcpClient(endPoint); + SimpleTcpClient4 = new JT808SimpleTcpClient(endPoint); + SimpleTcpClient5 = new JT808SimpleTcpClient(endPoint); + // 心跳会话包 + JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001"); + SimpleTcpClient1.WriteAsync(JT808Serializer.Serialize(jT808Package1)); + + // 心跳会话包 + JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002"); + SimpleTcpClient2.WriteAsync(JT808Serializer.Serialize(jT808Package2)); + + // 心跳会话包 + JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003"); + SimpleTcpClient3.WriteAsync(JT808Serializer.Serialize(jT808Package3)); + + // 心跳会话包 + JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004"); + SimpleTcpClient4.WriteAsync(JT808Serializer.Serialize(jT808Package4)); + + // 心跳会话包 + JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005"); + SimpleTcpClient5.WriteAsync(JT808Serializer.Serialize(jT808Package5)); + Thread.Sleep(1000); + } + + public void Dispose() + { + SimpleTcpClient1.Down(); + SimpleTcpClient2.Down(); + SimpleTcpClient3.Down(); + SimpleTcpClient4.Down(); + SimpleTcpClient5.Down(); + } + + [Fact] + public void Test1() + { + IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService(); + var result = jT808SessionServiceDefaultImpl.GetTcpAll(); + Thread.Sleep(5000); + } + + [Fact] + public void Test2() + { + IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService(); + var result1 = jT808SessionServiceDefaultImpl.GetTcpAll(); + var result2 = jT808SessionServiceDefaultImpl.RemoveByTerminalPhoneNo("123456789001"); + var result3 = jT808SessionServiceDefaultImpl.GetTcpAll(); + } + + [Fact] + public void Test3() + { + // 判断通道是否关闭 + IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService(); + JT808SessionManager jT808TcpSessionManager = ServiceProvider.GetService(); + var result1 = jT808SessionServiceDefaultImpl.GetTcpAll(); + SimpleTcpClient1.Down(); + Thread.Sleep(5000); + var session = jT808TcpSessionManager.GetSessionByTerminalPhoneNo("123456789001"); + Thread.Sleep(100000); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/Tcp/JT808UnificationTcpSendServiceTest.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Tcp/JT808UnificationTcpSendServiceTest.cs new file mode 100644 index 0000000..e5138a6 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Tcp/JT808UnificationTcpSendServiceTest.cs @@ -0,0 +1,75 @@ +using JT808.Protocol; +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; +using System.Threading; +using Microsoft.Extensions.DependencyInjection; +using JT808.Protocol.Extensions; +using JT808.Protocol.MessageBody; +using JT808.Gateway.Interfaces; +using JT808.Gateway.Simples; +using Xunit; +using JT808.Gateway.Dtos; + +namespace JT808.Gateway.Test.Tcp +{ + public class JT808UnificationTcpSendServiceTest: TestBase + { + static IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565); + + private IJT808UnificationSendService jT808UnificationSendService; + private IJT808SessionService jT808SessionServiceDefaultImpl; + + public JT808UnificationTcpSendServiceTest() + { + + JT808SimpleTcpClient SimpleTcpClient1 = new JT808SimpleTcpClient(endPoint); + JT808SimpleTcpClient SimpleTcpClient2 = new JT808SimpleTcpClient(endPoint); + JT808SimpleTcpClient SimpleTcpClient3 = new JT808SimpleTcpClient(endPoint); + JT808SimpleTcpClient SimpleTcpClient4 = new JT808SimpleTcpClient(endPoint); + JT808SimpleTcpClient SimpleTcpClient5 = new JT808SimpleTcpClient(endPoint); + // 心跳会话包 + JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001"); + SimpleTcpClient1.WriteAsync(JT808Serializer.Serialize(jT808Package1)); + + // 心跳会话包 + JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002"); + SimpleTcpClient2.WriteAsync(JT808Serializer.Serialize(jT808Package2)); + + // 心跳会话包 + JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003"); + SimpleTcpClient3.WriteAsync(JT808Serializer.Serialize(jT808Package3)); + + // 心跳会话包 + JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004"); + SimpleTcpClient4.WriteAsync(JT808Serializer.Serialize(jT808Package4)); + + // 心跳会话包 + JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005"); + SimpleTcpClient5.WriteAsync(JT808Serializer.Serialize(jT808Package5)); + + Thread.Sleep(300); + } + + [Fact] + public void Test1() + { + jT808SessionServiceDefaultImpl = ServiceProvider.GetService(); + jT808UnificationSendService = ServiceProvider.GetService(); + jT808SessionServiceDefaultImpl.GetTcpAll(); + string no = "123456789001"; + // 文本信息包 + JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.文本信息下发.Create(no, new JT808_0x8300 + { + TextFlag = 5, + TextInfo = "smallchi 518" + }); + var data = JT808Serializer.Serialize(jT808Package2); + JT808ResultDto jt808Result = jT808UnificationSendService.Send(no, data); + Thread.Sleep(1000); + Assert.Equal(200, jt808Result.Code); + Assert.True(jt808Result.Data); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/Tcp/TestBase.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Tcp/TestBase.cs new file mode 100644 index 0000000..2f9716f --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Tcp/TestBase.cs @@ -0,0 +1,43 @@ +using JT808.Gateway.Tcp; +using JT808.Protocol; +using JT808.Protocol.Interfaces; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace JT808.Gateway.Test.Tcp +{ + public class TestBase + { + public static IServiceProvider ServiceProvider; + public static JT808Serializer JT808Serializer; + static TestBase() + { + var serverHostBuilder = new HostBuilder() + .ConfigureAppConfiguration((hostingContext, config) => + { + config.SetBasePath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tcp")); + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); + }) + .ConfigureServices((hostContext, services) => + { + services.AddSingleton(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddJT808Configure() + .AddJT808Gateway(hostContext.Configuration) + .AddJT808GatewayTcpHost() + .Builder(); + //.Replace<>; + }); + var build = serverHostBuilder.Build(); + build.Start(); + ServiceProvider = build.Services; + JT808Serializer = ServiceProvider.GetRequiredService().GetSerializer(); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/Udp/JT808SessionServiceTest.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Udp/JT808SessionServiceTest.cs new file mode 100644 index 0000000..dedf7c4 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Udp/JT808SessionServiceTest.cs @@ -0,0 +1,92 @@ +using JT808.Protocol; +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; +using System.Threading; +using Microsoft.Extensions.DependencyInjection; +using JT808.Protocol.Extensions; +using Xunit; +using JT808.Gateway.Simples; +using JT808.Gateway.Interfaces; +using JT808.Gateway.Session; + +namespace JT808.Gateway.Test.Udp +{ + public class JT808SessionServiceTest:TestBase,IDisposable + { + static IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 818); + JT808SimpleUdpClient SimpleUdpClient1; + JT808SimpleUdpClient SimpleUdpClient2; + JT808SimpleUdpClient SimpleUdpClient3; + JT808SimpleUdpClient SimpleUdpClient4; + JT808SimpleUdpClient SimpleUdpClient5; + + public void Dispose() + { + SimpleUdpClient1.Down(); + SimpleUdpClient2.Down(); + SimpleUdpClient3.Down(); + SimpleUdpClient4.Down(); + SimpleUdpClient5.Down(); + } + + public JT808SessionServiceTest() + { + SimpleUdpClient1 = new JT808SimpleUdpClient(endPoint); + SimpleUdpClient2 = new JT808SimpleUdpClient(endPoint); + SimpleUdpClient3 = new JT808SimpleUdpClient(endPoint); + SimpleUdpClient4 = new JT808SimpleUdpClient(endPoint); + SimpleUdpClient5 = new JT808SimpleUdpClient(endPoint); + // 心跳会话包 + JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001"); + SimpleUdpClient1.WriteAsync(JT808Serializer.Serialize(jT808Package1)); + + // 心跳会话包 + JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002"); + SimpleUdpClient2.WriteAsync(JT808Serializer.Serialize(jT808Package2)); + + // 心跳会话包 + JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003"); + SimpleUdpClient3.WriteAsync(JT808Serializer.Serialize(jT808Package3)); + + // 心跳会话包 + JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004"); + SimpleUdpClient4.WriteAsync(JT808Serializer.Serialize(jT808Package4)); + + // 心跳会话包 + JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005"); + SimpleUdpClient5.WriteAsync(JT808Serializer.Serialize(jT808Package5)); + Thread.Sleep(1000); + } + + [Fact] + public void Test1() + { + IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService(); + var result = jT808SessionServiceDefaultImpl.GetUdpAll(); + } + + [Fact] + public void Test2() + { + IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService(); + var result1 = jT808SessionServiceDefaultImpl.GetUdpAll(); + var result2 = jT808SessionServiceDefaultImpl.RemoveByTerminalPhoneNo("123456789001"); + var result3 = jT808SessionServiceDefaultImpl.GetUdpAll(); + } + + [Fact] + public void Test3() + { + // 判断通道是否关闭 + IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService(); + JT808SessionManager jT808UdpSessionManager = ServiceProvider.GetService(); + var result1 = jT808SessionServiceDefaultImpl.GetUdpAll(); + SimpleUdpClient1.Down(); + var session = jT808UdpSessionManager.GetSessionByTerminalPhoneNo("123456789001"); + var result3 = jT808UdpSessionManager.GetUdpAll(); + Thread.Sleep(100000); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/Udp/JT808UnificationUdpSendServiceTest.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Udp/JT808UnificationUdpSendServiceTest.cs new file mode 100644 index 0000000..0f3cf87 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Udp/JT808UnificationUdpSendServiceTest.cs @@ -0,0 +1,76 @@ +using JT808.Protocol; +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; +using System.Threading; +using Microsoft.Extensions.DependencyInjection; +using JT808.Protocol.Extensions; +using JT808.Protocol.MessageBody; +using JT808.Gateway.Interfaces; +using JT808.Gateway.Simples; +using JT808.Gateway.Dtos; +using Xunit; + +namespace JT808.Gateway.Test.Udp +{ + + public class JT808UnificationUdpSendServiceTest : TestBase + { + static IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 818); + + private IJT808UnificationSendService jT808UnificationSendService; + private IJT808SessionService jT808SessionServiceDefaultImpl; + + public JT808UnificationUdpSendServiceTest() + { + JT808SimpleUdpClient SimpleUdpClient1 = new JT808SimpleUdpClient(endPoint); + JT808SimpleUdpClient SimpleUdpClient2 = new JT808SimpleUdpClient(endPoint); + JT808SimpleUdpClient SimpleUdpClient3 = new JT808SimpleUdpClient(endPoint); + JT808SimpleUdpClient SimpleUdpClient4 = new JT808SimpleUdpClient(endPoint); + JT808SimpleUdpClient SimpleUdpClient5 = new JT808SimpleUdpClient(endPoint); + // 心跳会话包 + JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001"); + SimpleUdpClient1.WriteAsync(JT808Serializer.Serialize(jT808Package1)); + + // 心跳会话包 + JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002"); + SimpleUdpClient2.WriteAsync(JT808Serializer.Serialize(jT808Package2)); + + // 心跳会话包 + JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003"); + SimpleUdpClient3.WriteAsync(JT808Serializer.Serialize(jT808Package3)); + + // 心跳会话包 + JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004"); + SimpleUdpClient4.WriteAsync(JT808Serializer.Serialize(jT808Package4)); + + // 心跳会话包 + JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005"); + SimpleUdpClient5.WriteAsync(JT808Serializer.Serialize(jT808Package5)); + + Thread.Sleep(300); + } + + [Fact] + public void Test1() + { + //"126 131 0 0 13 18 52 86 120 144 1 0 11 5 115 109 97 108 108 99 104 105 32 53 49 56 24 126" + jT808SessionServiceDefaultImpl = ServiceProvider.GetService(); + jT808UnificationSendService = ServiceProvider.GetService(); + jT808SessionServiceDefaultImpl.GetUdpAll(); + string no = "123456789001"; + // 文本信息包 + JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.文本信息下发.Create(no, new JT808_0x8300 + { + TextFlag = 5, + TextInfo = "smallchi 518" + }); + var data = JT808Serializer.Serialize(jT808Package2); + JT808ResultDto jt808Result = jT808UnificationSendService.Send(no, data); + Thread.Sleep(1000); + Assert.Equal(200, jt808Result.Code); + Assert.True(jt808Result.Data); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/Udp/TestBase.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Udp/TestBase.cs new file mode 100644 index 0000000..ecb1d9d --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Udp/TestBase.cs @@ -0,0 +1,41 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; +using JT808.Protocol; +using JT808.Protocol.Interfaces; +using JT808.Gateway.Udp; +using System.IO; + +namespace JT808.Gateway.Test.Udp +{ + public class TestBase + { + public static IServiceProvider ServiceProvider; + public static JT808Serializer JT808Serializer; + static TestBase() + { + var serverHostBuilder = new HostBuilder() + .ConfigureAppConfiguration((hostingContext, config) => + { + config.SetBasePath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"Udp")); + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); + }) + .ConfigureServices((hostContext, services) => + { + services.AddSingleton(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddJT808Configure() + .AddJT808Gateway(hostContext.Configuration) + .AddJT808GatewayUdpHost(); + }); + var build = serverHostBuilder.Build(); + build.Start(); + ServiceProvider = build.Services; + JT808Serializer = ServiceProvider.GetRequiredService().GetSerializer(); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Traffic.Test/JT808.Gateway.Traffic.Test.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.Traffic.Test/JT808.Gateway.Traffic.Test.csproj new file mode 100644 index 0000000..c6b1507 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Traffic.Test/JT808.Gateway.Traffic.Test.csproj @@ -0,0 +1,24 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + + Always + + + + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Traffic.Test/JT808DotNettyTrafficServiceTest.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Traffic.Test/JT808DotNettyTrafficServiceTest.cs new file mode 100644 index 0000000..741c65f --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Traffic.Test/JT808DotNettyTrafficServiceTest.cs @@ -0,0 +1,40 @@ +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.Kafka; +using JT808.Gateway.PubSub; +using JT808.Protocol.Extensions; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace JT808.Gateway.Traffic.Test +{ + public class JT808DotNettyTrafficServiceTest + { + private readonly CSRedis.CSRedisClient redisClien; + public readonly ILogger logger; + public JT808DotNettyTrafficServiceTest(ILoggerFactory loggerFactory) { + redisClien = new CSRedis.CSRedisClient("127.0.0.1:6379,password=smallchi"); + RedisHelper.Initialization(redisClien); + logger = loggerFactory.CreateLogger(); + Task.Run(() => { + while (true) + { + Thread.Sleep(5000); + using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig + { + BootstrapServers = "127.0.0.1:9092", + TopicName = "JT808Msg" + })) + { + jT808MsgProducer.ProduceAsync("011111111111", "7E02000032011111111111012E00000000000C00000160E42506C30C82002C00000000180914142057010400001DC003020000250400000000300115310100977E".ToHexBytes()).Wait(); + } + var length= RedisHelper.HGet("011111111111", DateTime.Now.ToString("yyyyMMdd")); + logger.LogDebug($"{011111111111}:{length}"); + } + }); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Traffic.Test/Program.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Traffic.Test/Program.cs new file mode 100644 index 0000000..8a3f615 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Traffic.Test/Program.cs @@ -0,0 +1,44 @@ +using JT808.Gateway.BusinessServices.Traffic; +using JT808.Gateway.Kafka; +using JT808.Protocol; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Threading.Tasks; + +namespace JT808.Gateway.Traffic.Test +{ + class Program + { + async static Task Main(string[] args) + { + var hostBuilder = new HostBuilder() + .UseEnvironment(args[0].Split('=')[1]) + .ConfigureAppConfiguration((hostContext, config) => { + config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); + }) + .ConfigureLogging((hostContext, configLogging) => { + configLogging.AddConsole(); + configLogging.SetMinimumLevel(LogLevel.Trace); + }) + .ConfigureServices((hostContext, services) => { + services.AddSingleton(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddSingleton(); + services.AddJT808Configure() + .AddJT808ClientKafka() + .AddMsgConsumer(hostContext.Configuration) + .AddInprocJT808Traffic(); + + services.BuildServiceProvider().GetRequiredService(); + }) + ; + + await hostBuilder.RunConsoleAsync(); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Transmit.Test/JT808.Gateway.Transmit.Test.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.Transmit.Test/JT808.Gateway.Transmit.Test.csproj new file mode 100644 index 0000000..37cd0df --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Transmit.Test/JT808.Gateway.Transmit.Test.csproj @@ -0,0 +1,24 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + + Always + + + + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Transmit.Test/JT808DotNettyTransmitServiceTest.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Transmit.Test/JT808DotNettyTransmitServiceTest.cs new file mode 100644 index 0000000..d91df89 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Transmit.Test/JT808DotNettyTransmitServiceTest.cs @@ -0,0 +1,35 @@ +using JT808.Gateway.Configs.Kafka; +using JT808.Gateway.Kafka; +using JT808.Gateway.PubSub; +using JT808.Protocol.Extensions; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace JT808.Gateway.Transmit.Test +{ + public class JT808DotNettyTransmitServiceTest + { + public readonly ILogger logger; + public JT808DotNettyTransmitServiceTest(ILoggerFactory loggerFactory) { + logger = loggerFactory.CreateLogger(); + Task.Run(() => { + while (true) + { + Thread.Sleep(5000); + using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig + { + BootstrapServers = "127.0.0.1:9092", + TopicName = "JT808Msg" + })) + { + jT808MsgProducer.ProduceAsync("011111111111", "7E02000032011111111111012E00000000000C00000160E42506C30C82002C00000000180914142057010400001DC003020000250400000000300115310100977E".ToHexBytes()).Wait(); + } + } + }); + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Transmit.Test/Program.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Transmit.Test/Program.cs new file mode 100644 index 0000000..d188fb1 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Transmit.Test/Program.cs @@ -0,0 +1,43 @@ +using JT808.Gateway.BusinessServices.Transmit; +using JT808.Gateway.Kafka; +using JT808.Protocol; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Threading.Tasks; + +namespace JT808.Gateway.Transmit.Test +{ + class Program + { + async static Task Main(string[] args) + { + var hostBuilder = new HostBuilder() + .UseEnvironment(args[0].Split('=')[1]) + .ConfigureAppConfiguration((hostContext, config) => { + config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); + config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); + }) + .ConfigureLogging((hostContext, configLogging) => { + configLogging.AddConsole(); + configLogging.SetMinimumLevel(LogLevel.Trace); + }) + .ConfigureServices((hostContext, services) => { + services.AddSingleton(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddSingleton(); + services.AddJT808Configure() + .AddJT808ClientKafka() + .AddMsgConsumer(hostContext.Configuration) + .AddInprocJT808Transmit(hostContext.Configuration); + services.BuildServiceProvider().GetRequiredService(); + }) + ; + + await hostBuilder.RunConsoleAsync(); + } + } +} diff --git a/src/JT808.Gateway.sln b/src/JT808.Gateway.sln index 546cc35..b6b12d5 100644 --- a/src/JT808.Gateway.sln +++ b/src/JT808.Gateway.sln @@ -9,6 +9,26 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.SimpleServer" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.SimpleClient", "JT808.Gateway.SimpleClient\JT808.Gateway.SimpleClient.csproj", "{886D4937-7265-40DC-87CC-85CE35553214}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.Kafka", "JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj", "{790E132C-7D92-4A6A-8CF0-2C181331FB31}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.CleintBenchmark", "JT808.Gateway.CleintBenchmark\JT808.Gateway.CleintBenchmark.csproj", "{1A925C08-2590-4E55-84F2-96F01306D34D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{DC0E0AC1-C4BD-4291-AD16-744080411C3D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Traffic.Test", "JT808.Gateway.Tests\JT808.Gateway.Traffic.Test\JT808.Gateway.Traffic.Test.csproj", "{D4DF5285-612A-417D-BDE4-690BDF0C07C6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Transmit.Test", "JT808.Gateway.Tests\JT808.Gateway.Transmit.Test\JT808.Gateway.Transmit.Test.csproj", "{5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.SessionNotice.Test", "JT808.Gateway.Tests\JT808.Gateway.SessionNotice.Test\JT808.Gateway.SessionNotice.Test.csproj", "{562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.ReplyMessage.Test", "JT808.Gateway.Tests\JT808.Gateway.ReplyMessage.Test\JT808.Gateway.ReplyMessage.Test.csproj", "{CDE064DE-0E8E-4165-8F6A-6C03A8783506}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.MsgLogging.Test", "JT808.Gateway.Tests\JT808.Gateway.MsgLogging.Test\JT808.Gateway.MsgLogging.Test.csproj", "{8BD638B1-1F16-4BA8-8506-1B83DA4A884E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.MsgIdHandler.Test", "JT808.Gateway.Tests\JT808.Gateway.MsgIdHandler.Test\JT808.Gateway.MsgIdHandler.Test.csproj", "{CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.Test", "JT808.Gateway.Tests\JT808.Gateway.Test\JT808.Gateway.Test.csproj", "{F1031636-69CF-4C44-AF0B-F8BE8DE03864}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,10 +47,55 @@ Global {886D4937-7265-40DC-87CC-85CE35553214}.Debug|Any CPU.Build.0 = Debug|Any CPU {886D4937-7265-40DC-87CC-85CE35553214}.Release|Any CPU.ActiveCfg = Release|Any CPU {886D4937-7265-40DC-87CC-85CE35553214}.Release|Any CPU.Build.0 = Release|Any CPU + {790E132C-7D92-4A6A-8CF0-2C181331FB31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {790E132C-7D92-4A6A-8CF0-2C181331FB31}.Debug|Any CPU.Build.0 = Debug|Any CPU + {790E132C-7D92-4A6A-8CF0-2C181331FB31}.Release|Any CPU.ActiveCfg = Release|Any CPU + {790E132C-7D92-4A6A-8CF0-2C181331FB31}.Release|Any CPU.Build.0 = Release|Any CPU + {1A925C08-2590-4E55-84F2-96F01306D34D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A925C08-2590-4E55-84F2-96F01306D34D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A925C08-2590-4E55-84F2-96F01306D34D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A925C08-2590-4E55-84F2-96F01306D34D}.Release|Any CPU.Build.0 = Release|Any CPU + {D4DF5285-612A-417D-BDE4-690BDF0C07C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4DF5285-612A-417D-BDE4-690BDF0C07C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4DF5285-612A-417D-BDE4-690BDF0C07C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4DF5285-612A-417D-BDE4-690BDF0C07C6}.Release|Any CPU.Build.0 = Release|Any CPU + {5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}.Release|Any CPU.Build.0 = Release|Any CPU + {562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}.Release|Any CPU.Build.0 = Release|Any CPU + {CDE064DE-0E8E-4165-8F6A-6C03A8783506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDE064DE-0E8E-4165-8F6A-6C03A8783506}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDE064DE-0E8E-4165-8F6A-6C03A8783506}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDE064DE-0E8E-4165-8F6A-6C03A8783506}.Release|Any CPU.Build.0 = Release|Any CPU + {8BD638B1-1F16-4BA8-8506-1B83DA4A884E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8BD638B1-1F16-4BA8-8506-1B83DA4A884E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8BD638B1-1F16-4BA8-8506-1B83DA4A884E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8BD638B1-1F16-4BA8-8506-1B83DA4A884E}.Release|Any CPU.Build.0 = Release|Any CPU + {CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}.Release|Any CPU.Build.0 = Release|Any CPU + {F1031636-69CF-4C44-AF0B-F8BE8DE03864}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1031636-69CF-4C44-AF0B-F8BE8DE03864}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1031636-69CF-4C44-AF0B-F8BE8DE03864}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1031636-69CF-4C44-AF0B-F8BE8DE03864}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D4DF5285-612A-417D-BDE4-690BDF0C07C6} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} + {5E2C290C-637B-4F8B-AE03-1A4B669F7FFB} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} + {562B16BD-1D4C-40FD-86CF-7845DBC9C1EE} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} + {CDE064DE-0E8E-4165-8F6A-6C03A8783506} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} + {8BD638B1-1F16-4BA8-8506-1B83DA4A884E} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} + {CC2ABC8E-CC78-4B68-8670-90C2BCAB434E} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} + {F1031636-69CF-4C44-AF0B-F8BE8DE03864} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F5671BD2-B44A-4A7C-80EA-E060A512992D} EndGlobalSection diff --git a/src/JT808.Gateway/BusinessServices/MsgIdHandler/IJT808MsgIdHandler.cs b/src/JT808.Gateway/BusinessServices/MsgIdHandler/IJT808MsgIdHandler.cs new file mode 100644 index 0000000..59bf986 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/MsgIdHandler/IJT808MsgIdHandler.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.MsgIdHandler +{ + /// + /// JT808消息Id处理程序 + /// + public interface IJT808MsgIdHandler + { + void Processor((string TerminalNo, byte[] Data) parameter); + } +} diff --git a/src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerExtensions.cs b/src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerExtensions.cs new file mode 100644 index 0000000..433e065 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerExtensions.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.MsgIdHandler +{ + public static class JT808MsgIdHandlerExtensions + { + public static IJT808ClientBuilder AddJT808MsgIdHandler(this IJT808ClientBuilder jT808ClientBuilder) + where TJT808MsgIdHandler: IJT808MsgIdHandler + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(typeof(IJT808MsgIdHandler),typeof(TJT808MsgIdHandler)); + jT808ClientBuilder.JT808Builder.Services.AddHostedService(); + return jT808ClientBuilder; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerHostedService.cs b/src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerHostedService.cs new file mode 100644 index 0000000..d85eb04 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerHostedService.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using System.Threading; +using JT808.Gateway.PubSub; + +namespace JT808.Gateway.BusinessServices.MsgIdHandler +{ + public class JT808MsgIdHandlerHostedService : IHostedService + { + private readonly IJT808MsgConsumer jT808MsgConsumer; + + private readonly IJT808MsgIdHandler jT808MsgIdHandler; + public JT808MsgIdHandlerHostedService( + IJT808MsgIdHandler jT808DotNettyMsgIdHandler, + IJT808MsgConsumer jT808MsgConsumer) + { + this.jT808MsgIdHandler = jT808DotNettyMsgIdHandler; + this.jT808MsgConsumer = jT808MsgConsumer; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Subscribe(); + jT808MsgConsumer.OnMessage(jT808MsgIdHandler.Processor); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Unsubscribe(); + return Task.CompletedTask; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/MsgLogging/IJT808MsgLogging.cs b/src/JT808.Gateway/BusinessServices/MsgLogging/IJT808MsgLogging.cs new file mode 100644 index 0000000..b3daf96 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/MsgLogging/IJT808MsgLogging.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace JT808.Gateway.BusinessServices.MsgLogging +{ + /// + /// 808数据上下行日志接口 + /// + public interface IJT808MsgLogging + { + void Processor((string TerminalNo, byte[] Data) parameter, JT808MsgLoggingType jT808MsgLoggingType); + } +} diff --git a/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgDownLoggingHostedService.cs b/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgDownLoggingHostedService.cs new file mode 100644 index 0000000..7c52f15 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgDownLoggingHostedService.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using System.Threading; +using JT808.Gateway.PubSub; + +namespace JT808.Gateway.BusinessServices.MsgLogging +{ + public class JT808MsgDownLoggingHostedService : IHostedService + { + private readonly IJT808MsgReplyConsumer jT808MsgReplyConsumer; + private readonly IJT808MsgLogging jT808MsgLogging; + public JT808MsgDownLoggingHostedService( + IJT808MsgLogging jT808MsgLogging, + IJT808MsgReplyConsumer jT808MsgReplyConsumer) + { + this.jT808MsgReplyConsumer = jT808MsgReplyConsumer; + this.jT808MsgLogging = jT808MsgLogging; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + jT808MsgReplyConsumer.Subscribe(); + jT808MsgReplyConsumer.OnMessage(item=> + { + jT808MsgLogging.Processor(item, JT808MsgLoggingType.down); + }); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + jT808MsgReplyConsumer.Unsubscribe(); + return Task.CompletedTask; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingExtensions.cs b/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingExtensions.cs new file mode 100644 index 0000000..00f16ac --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingExtensions.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.MsgLogging +{ + public static class JT808MsgLoggingExtensions + { + public static IJT808ClientBuilder AddJT808MsgLogging(this IJT808ClientBuilder jT808ClientBuilder) + where TJT808MsgLogging: IJT808MsgLogging + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(typeof(IJT808MsgLogging),typeof(TJT808MsgLogging)); + jT808ClientBuilder.JT808Builder.Services.AddHostedService(); + jT808ClientBuilder.JT808Builder.Services.AddHostedService(); + return jT808ClientBuilder; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingType.cs b/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingType.cs new file mode 100644 index 0000000..1c83329 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingType.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.MsgLogging +{ + public enum JT808MsgLoggingType + { + /// + /// 数据上行 + /// + up, + /// + /// 数据下行 + /// + down + } +} diff --git a/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgUpLoggingHostedService.cs b/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgUpLoggingHostedService.cs new file mode 100644 index 0000000..be257b7 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgUpLoggingHostedService.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using System.Threading; +using JT808.Gateway.PubSub; + +namespace JT808.Gateway.BusinessServices.MsgLogging +{ + public class JT808MsgUpLoggingHostedService : IHostedService + { + private readonly IJT808MsgConsumer jT808MsgConsumer; + private readonly IJT808MsgLogging jT808MsgLogging; + public JT808MsgUpLoggingHostedService( + IJT808MsgLogging jT808MsgLogging, + IJT808MsgConsumer jT808MsgConsumer) + { + this.jT808MsgConsumer = jT808MsgConsumer; + this.jT808MsgLogging = jT808MsgLogging; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Subscribe(); + jT808MsgConsumer.OnMessage(item=> + { + jT808MsgLogging.Processor(item, JT808MsgLoggingType.up); + }); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Unsubscribe(); + return Task.CompletedTask; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageExtensions.cs b/src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageExtensions.cs new file mode 100644 index 0000000..049f824 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageExtensions.cs @@ -0,0 +1,57 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.ReplyMessage +{ + public static class JT808ReplyMessageExtensions + { + /// + /// 独享消息应答服务(不同的消费者实例) + /// + /// + /// + public static IJT808ClientBuilder AddInprocJT808ReplyMessage(this IJT808ClientBuilder jT808ClientBuilder) + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + jT808ClientBuilder.JT808Builder.Services.AddHostedService(); + return jT808ClientBuilder; + } + /// + /// 独享消息应答服务(不同的消费者实例) + /// + /// 自定义消息回复服务 + /// + /// + public static IJT808ClientBuilder AddInprocJT808ReplyMessage(this IJT808ClientBuilder jT808ClientBuilder) + where TReplyMessageService : JT808ReplyMessageService + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + jT808ClientBuilder.JT808Builder.Services.AddHostedService(); + return jT808ClientBuilder; + } + /// + /// 共享消息应答服务(消费者单实例) + /// + /// 自定义消息回复服务 + /// + /// + public static IJT808ClientBuilder AddShareJT808ReplyMessage(this IJT808ClientBuilder jT808ClientBuilder) + where TReplyMessageService : JT808ReplyMessageService + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + return jT808ClientBuilder; + } + /// + /// 共享消息应答服务(消费者单实例) + /// + /// + /// + public static IJT808ClientBuilder AddShareJT808ReplyMessage(this IJT808ClientBuilder jT808ClientBuilder) + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + return jT808ClientBuilder; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageHostedService.cs b/src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageHostedService.cs new file mode 100644 index 0000000..1bd7e74 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageHostedService.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using System.Threading; +using JT808.Gateway.PubSub; + +namespace JT808.Gateway.BusinessServices.ReplyMessage +{ + public class JT808ReplyMessageHostedService : IHostedService + { + private readonly IJT808MsgConsumer jT808MsgConsumer; + private readonly JT808ReplyMessageService jT808DotNettyReplyMessageService; + + public JT808ReplyMessageHostedService( + JT808ReplyMessageService jT808DotNettyReplyMessageService, + IJT808MsgConsumer jT808MsgConsumer) + { + this.jT808MsgConsumer = jT808MsgConsumer; + this.jT808DotNettyReplyMessageService = jT808DotNettyReplyMessageService; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Subscribe(); + jT808MsgConsumer.OnMessage(jT808DotNettyReplyMessageService.Processor); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Unsubscribe(); + return Task.CompletedTask; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageService.cs b/src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageService.cs new file mode 100644 index 0000000..3fc64f6 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageService.cs @@ -0,0 +1,165 @@ +using JT808.Gateway.PubSub; +using JT808.Protocol; +using JT808.Protocol.Enums; +using JT808.Protocol.Extensions; +using JT808.Protocol.MessageBody; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.ReplyMessage +{ + public class JT808ReplyMessageService + { + protected Dictionary> HandlerDict { get; } + + protected JT808Serializer JT808Serializer { get; } + protected IJT808MsgReplyProducer JT808MsgReplyProducer { get; } + public JT808ReplyMessageService( + IJT808Config jT808Config, + IJT808MsgReplyProducer jT808MsgReplyProducer) + { + this.JT808Serializer = jT808Config.GetSerializer(); + this.JT808MsgReplyProducer = jT808MsgReplyProducer; + HandlerDict = new Dictionary> { + {JT808MsgId.终端通用应答.ToUInt16Value(), Msg0x0001}, + {JT808MsgId.终端鉴权.ToUInt16Value(), Msg0x0102}, + {JT808MsgId.终端心跳.ToUInt16Value(), Msg0x0002}, + {JT808MsgId.终端注销.ToUInt16Value(), Msg0x0003}, + {JT808MsgId.终端注册.ToUInt16Value(), Msg0x0100}, + {JT808MsgId.位置信息汇报.ToUInt16Value(),Msg0x0200 }, + {JT808MsgId.定位数据批量上传.ToUInt16Value(),Msg0x0704 }, + {JT808MsgId.数据上行透传.ToUInt16Value(),Msg0x0900 } + }; + } + + public virtual void Processor((string TerminalNo, byte[] Data) parameter) + { + try + { + var request = JT808Serializer.HeaderDeserialize(parameter.Data); + if (HandlerDict.TryGetValue(request.Header.MsgId, out var func)) + { + var buffer = func(request); + if (buffer != null) + { + JT808MsgReplyProducer.ProduceAsync(parameter.TerminalNo, buffer); + } + } + } + catch + { + } + } + + /// + /// 终端通用应答 + /// 平台无需回复 + /// 实现自己的业务 + /// + /// + /// + public virtual byte[] Msg0x0001(JT808HeaderPackage request) + { + return null; + } + /// + /// 终端心跳 + /// + /// + /// + public virtual byte[] Msg0x0002(JT808HeaderPackage request) + { + return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() + { + MsgId = request.Header.MsgId, + JT808PlatformResult = JT808PlatformResult.成功, + MsgNum = request.Header.MsgNum + })); + } + /// + /// 终端注销 + /// + /// + /// + public virtual byte[] Msg0x0003(JT808HeaderPackage request) + { + return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() + { + MsgId = request.Header.MsgId, + JT808PlatformResult = JT808PlatformResult.成功, + MsgNum = request.Header.MsgNum + })); + } + /// + /// 终端注册 + /// + /// + /// + public virtual byte[] Msg0x0100(JT808HeaderPackage request) + { + return JT808Serializer.Serialize(JT808MsgId.终端注册应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8100() + { + Code = "J" + request.Header.TerminalPhoneNo, + JT808TerminalRegisterResult = JT808TerminalRegisterResult.成功, + MsgNum = request.Header.MsgNum + })); + } + /// + /// 终端鉴权 + /// + /// + /// + public virtual byte[] Msg0x0102(JT808HeaderPackage request) + { + return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() + { + MsgId = request.Header.MsgId, + JT808PlatformResult = JT808PlatformResult.成功, + MsgNum = request.Header.MsgNum + })); + } + /// + /// 位置信息汇报 + /// + /// + /// + public virtual byte[] Msg0x0200(JT808HeaderPackage request) + { + return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() + { + MsgId = request.Header.MsgId, + JT808PlatformResult = JT808PlatformResult.成功, + MsgNum = request.Header.MsgNum + })); + } + /// + /// 定位数据批量上传 + /// + /// + /// + public virtual byte[] Msg0x0704(JT808HeaderPackage request) + { + return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() + { + MsgId = request.Header.MsgId, + JT808PlatformResult = JT808PlatformResult.成功, + MsgNum = request.Header.MsgNum + })); + } + /// + /// 数据上行透传 + /// + /// + /// + public virtual byte[] Msg0x0900(JT808HeaderPackage request) + { + return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() + { + MsgId = request.Header.MsgId, + JT808PlatformResult = JT808PlatformResult.成功, + MsgNum = request.Header.MsgNum + })); + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeExtensions.cs b/src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeExtensions.cs new file mode 100644 index 0000000..c2c3b9b --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeExtensions.cs @@ -0,0 +1,60 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.SessionNotice +{ + public static class JT808SessionNoticeExtensions + { + /// + /// 独享消息会话通知服务(不同的消费者实例) + /// + /// + /// + public static IJT808ClientBuilder AddInprocJT808SessionNotice(this IJT808ClientBuilder jT808ClientBuilder) + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + jT808ClientBuilder.JT808Builder.Services.AddHostedService(); + return jT808ClientBuilder; + } + + /// + /// 独享消息会话通知服务(不同的消费者实例) + /// + /// 自定义会话通知服务 + /// + /// + public static IJT808ClientBuilder AddInprocJT808SessionNotice(this IJT808ClientBuilder jT808ClientBuilder) + where TSessionNoticeService : JT808SessionNoticeService + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + jT808ClientBuilder.JT808Builder.Services.AddHostedService(); + return jT808ClientBuilder; + } + + /// + /// 共享消息会话通知服务(消费者单实例) + /// + /// 自定义会话通知服务 + /// + /// + public static IJT808ClientBuilder AddShareJT808SessionNotice(this IJT808ClientBuilder jT808ClientBuilder) + where TSessionNoticeService : JT808SessionNoticeService + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + return jT808ClientBuilder; + } + + /// + /// 共享消息会话通知服务(消费者单实例) + /// + /// + /// + public static IJT808ClientBuilder AddShareJT808SessionNotice(this IJT808ClientBuilder jT808ClientBuilder) + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + return jT808ClientBuilder; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeHostedService.cs b/src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeHostedService.cs new file mode 100644 index 0000000..44c04ae --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeHostedService.cs @@ -0,0 +1,35 @@ +using System.Threading.Tasks; +using JT808.Protocol; +using JT808.Protocol.Interfaces; +using Microsoft.Extensions.Hosting; +using System.Threading; +using JT808.Gateway.PubSub; + +namespace JT808.Gateway.BusinessServices.SessionNotice +{ + public class JT808SessionNoticeHostedService : IHostedService + { + private readonly JT808SessionNoticeService jT808DotNettySessionNoticeService; + private readonly IJT808SessionConsumer jT808SessionConsumer; + public JT808SessionNoticeHostedService( + IJT808SessionConsumer jT808SessionConsumer, + JT808SessionNoticeService jT808DotNettySessionNoticeService) + { + this.jT808DotNettySessionNoticeService = jT808DotNettySessionNoticeService; + this.jT808SessionConsumer = jT808SessionConsumer; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + jT808SessionConsumer.Subscribe(); + jT808SessionConsumer.OnMessage(jT808DotNettySessionNoticeService.Processor); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + jT808SessionConsumer.Unsubscribe(); + return Task.CompletedTask; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeService.cs b/src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeService.cs new file mode 100644 index 0000000..ccf4ace --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeService.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.SessionNotice +{ + public class JT808SessionNoticeService + { + protected ILogger logger { get; } + public JT808SessionNoticeService(ILoggerFactory loggerFactory) + { + logger = loggerFactory.CreateLogger("JT808DotNettySessionNoticeService"); + } + public virtual void Processor((string Notice, string TerminalNo) parameter) + { + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug($"{parameter.Notice}-{parameter.TerminalNo}"); + } + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficService.cs b/src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficService.cs new file mode 100644 index 0000000..f028a5d --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficService.cs @@ -0,0 +1,32 @@ +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.Traffic +{ + public class JT808TrafficService:IDisposable + { + private readonly CSRedis.CSRedisClient redisClien; + public JT808TrafficService(IConfiguration configuration) + { + redisClien = new CSRedis.CSRedisClient(configuration.GetConnectionString("TrafficRedisHost")); + TrafficRedisClient.Initialization(redisClien); + } + + public void Dispose() + { + redisClien.Dispose(); + } + + /// + /// 按设备每天统计sim卡流量 + /// + /// + /// + public void Processor(string terminalNo,int len) + { + TrafficRedisClient.HIncrBy(terminalNo, DateTime.Now.ToString("yyyyMMdd"), len); + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceExtensions.cs b/src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceExtensions.cs new file mode 100644 index 0000000..4a83b0d --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceExtensions.cs @@ -0,0 +1,33 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.Traffic +{ + public static class JT808TrafficServiceExtensions + { + /// + /// 独享消息流量统计服务(不同的消费者实例) + /// + /// + /// + public static IJT808ClientBuilder AddInprocJT808Traffic(this IJT808ClientBuilder jT808ClientBuilder) + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + jT808ClientBuilder.JT808Builder.Services.AddHostedService(); + return jT808ClientBuilder; + } + /// + /// 共享消息流量统计服务(消费者单实例) + /// + /// + /// + /// + public static IJT808ClientBuilder AddShareJT808Traffic(this IJT808ClientBuilder jT808ClientBuilder) + { + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + return jT808ClientBuilder; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceHostedService.cs b/src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceHostedService.cs new file mode 100644 index 0000000..84c4299 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceHostedService.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using System.Threading; +using JT808.Protocol.Extensions; +using JT808.Gateway.PubSub; + +namespace JT808.Gateway.BusinessServices.Traffic +{ + public class JT808TrafficServiceHostedService : IHostedService + { + private readonly IJT808MsgConsumer jT808MsgConsumer; + private readonly JT808TrafficService jT808DotNettyTrafficService; + + public JT808TrafficServiceHostedService( + JT808TrafficService jT808DotNettyTrafficService, + IJT808MsgConsumer jT808MsgConsumer) + { + this.jT808MsgConsumer = jT808MsgConsumer; + this.jT808DotNettyTrafficService = jT808DotNettyTrafficService; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Subscribe(); + jT808MsgConsumer.OnMessage((item)=> { + string str = item.Data.ToHexString(); + jT808DotNettyTrafficService.Processor(item.TerminalNo, item.Data.Length); + }); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Unsubscribe(); + return Task.CompletedTask; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/Traffic/TrafficRedisClient.cs b/src/JT808.Gateway/BusinessServices/Traffic/TrafficRedisClient.cs new file mode 100644 index 0000000..eb04aa0 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Traffic/TrafficRedisClient.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.Traffic +{ + class TrafficRedisClient: RedisHelper + { } +} diff --git a/src/JT808.Gateway/BusinessServices/Transmit/Configs/DataTransferOptions.cs b/src/JT808.Gateway/BusinessServices/Transmit/Configs/DataTransferOptions.cs new file mode 100644 index 0000000..5a50189 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Transmit/Configs/DataTransferOptions.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.Transmit.Configs +{ + public class DataTransferOptions + { + public string Host { get; set; } + + public List TerminalNos { get; set; } + } +} diff --git a/src/JT808.Gateway/BusinessServices/Transmit/Configs/RemoteServerOptions.cs b/src/JT808.Gateway/BusinessServices/Transmit/Configs/RemoteServerOptions.cs new file mode 100644 index 0000000..b9872cb --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Transmit/Configs/RemoteServerOptions.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.Gateway.BusinessServices.Transmit.Configs +{ + public class RemoteServerOptions + { + public List DataTransfer { get; set; } + } +} diff --git a/src/JT808.Gateway/BusinessServices/Transmit/Handlers/ClientConnectionHandler.cs b/src/JT808.Gateway/BusinessServices/Transmit/Handlers/ClientConnectionHandler.cs new file mode 100644 index 0000000..397b063 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Transmit/Handlers/ClientConnectionHandler.cs @@ -0,0 +1,76 @@ +using DotNetty.Transport.Bootstrapping; +using DotNetty.Transport.Channels; +using DotNetty.Transport.Channels.Sockets; +using Polly; +using System; +using System.Linq; +using System.Collections.Generic; +using System.Net; +using System.Text; +using Microsoft.Extensions.Logging; + +namespace JT808.Gateway.BusinessServices.Transmit.Handlers +{ + public class ClientConnectionHandler : ChannelHandlerAdapter + { + private readonly Bootstrap bootstrap; + public Dictionary channeldic; + private readonly ILogger logger; + public ClientConnectionHandler(Bootstrap bootstrap, + Dictionary channeldic, + ILoggerFactory loggerFactory) + { + this.bootstrap = bootstrap; + this.channeldic = channeldic; + logger = loggerFactory.CreateLogger(); + } + public override void ChannelInactive(IChannelHandlerContext context) + { + Policy.HandleResult(context.Channel.Open) + .WaitAndRetryForeverAsync(retryAttempt => + { + return retryAttempt > 20 ? TimeSpan.FromSeconds(Math.Pow(2, 50)) : TimeSpan.FromSeconds(Math.Pow(2, retryAttempt));//超过重试20次,之后重试都是接近12个小时重试一次 + }, + (exception, timespan, ctx) => + { + logger.LogError($"服务端断开{context.Channel.RemoteAddress},重试结果{exception.Result},重试次数{timespan},下次重试间隔(s){ctx.TotalSeconds}"); + }) + .ExecuteAsync(async () => + { + try + { + var oldChannel = channeldic.FirstOrDefault(m => m.Value == context.Channel); + if (default(KeyValuePair).Equals(oldChannel)) + { + if(logger.IsEnabled( LogLevel.Debug)) + logger.LogDebug($"服务器已经删除了{oldChannel.Key}远程服务器配置"); + return true; + } + var channel = await bootstrap.ConnectAsync(context.Channel.RemoteAddress); + channeldic.Remove(oldChannel.Key); + channeldic.Add(oldChannel.Key, channel); + return channel.Open; + } + catch (Exception ex) + { + logger.LogError($"服务端断开后{context.Channel.RemoteAddress},重连异常:{ex}"); + return false; + } + }); + } + + public override void ChannelRead(IChannelHandlerContext context, object message) + { + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogError($"服务端返回消息{message}"); + } + } + + public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) + { + logger.LogError($"服务端Exception: {exception}"); + context.CloseAsync(); + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitExtensions.cs b/src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitExtensions.cs new file mode 100644 index 0000000..969b2fd --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitExtensions.cs @@ -0,0 +1,39 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; +using JT808.Protocol; +using Microsoft.Extensions.Configuration; +using JT808.Gateway.BusinessServices.Transmit.Configs; + +namespace JT808.Gateway.BusinessServices.Transmit +{ + public static class JT808DotNettyTransmitExtensions + { + /// + /// 独享转发服务(不同的消费者实例) + /// + /// + /// + /// + public static IJT808ClientBuilder AddInprocJT808Transmit(this IJT808ClientBuilder jT808ClientBuilder,IConfiguration configuration) + { + jT808ClientBuilder.JT808Builder.Services.Configure(configuration.GetSection("RemoteServerOptions")); + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + jT808ClientBuilder.JT808Builder.Services.AddHostedService(); + return jT808ClientBuilder; + } + /// + /// 共享转发服务(消费者单实例) + /// + /// + /// + /// + public static IJT808ClientBuilder AddShareJT808Transmit(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) + { + jT808ClientBuilder.JT808Builder.Services.Configure(configuration.GetSection("RemoteServerOptions")); + jT808ClientBuilder.JT808Builder.Services.AddSingleton(); + return jT808ClientBuilder; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitHostedService.cs b/src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitHostedService.cs new file mode 100644 index 0000000..51504b5 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitHostedService.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using System.Threading; +using JT808.Gateway.PubSub; + +namespace JT808.Gateway.BusinessServices.Transmit +{ + public class JT808DotNettyTransmitHostedService:IHostedService + { + private readonly JT808DotNettyTransmitService jT808DotNettyTransmitService; + private readonly IJT808MsgConsumer jT808MsgConsumer; + public JT808DotNettyTransmitHostedService( + IJT808MsgConsumer jT808MsgConsumer, + JT808DotNettyTransmitService jT808DotNettyTransmitService) + { + this.jT808DotNettyTransmitService = jT808DotNettyTransmitService; + this.jT808MsgConsumer = jT808MsgConsumer; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Subscribe(); + jT808MsgConsumer.OnMessage(jT808DotNettyTransmitService.Send); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + jT808MsgConsumer.Unsubscribe(); + return Task.CompletedTask; + } + } +} diff --git a/src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitService.cs b/src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitService.cs new file mode 100644 index 0000000..1c2d8c3 --- /dev/null +++ b/src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitService.cs @@ -0,0 +1,236 @@ +using DotNetty.Buffers; +using DotNetty.Transport.Bootstrapping; +using DotNetty.Transport.Channels; +using DotNetty.Transport.Channels.Sockets; +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System.Linq; +using JT808.Gateway.BusinessServices.Transmit.Configs; +using JT808.Gateway.BusinessServices.Transmit.Handlers; + +namespace JT808.Gateway.BusinessServices.Transmit +{ + public class JT808DotNettyTransmitService + { + private readonly ILogger logger; + private readonly ILoggerFactory loggerFactory; + private IOptionsMonitor optionsMonitor; + public Dictionary channeldic = new Dictionary(); + public JT808DotNettyTransmitService(ILoggerFactory loggerFactory, + IOptionsMonitor optionsMonitor) + { + this.loggerFactory = loggerFactory; + logger = loggerFactory.CreateLogger("JT808DotNettyTransmitService"); + this.optionsMonitor = optionsMonitor; + InitialDispatcherClient(); + } + public void Send((string TerminalNo, byte[] Data) parameter) + { + if (optionsMonitor.CurrentValue.DataTransfer != null) + { + foreach (var item in optionsMonitor.CurrentValue.DataTransfer) + { + if (channeldic.TryGetValue($"all_{item.Host}", out var allClientChannel)) + { + try + { + if (allClientChannel.Open) + { + if (logger.IsEnabled(LogLevel.Debug)) + { + logger.LogDebug($"转发所有数据到该网关{item.Host}"); + } + allClientChannel.WriteAndFlushAsync(Unpooled.WrappedBuffer(parameter.Data)); + } + else + { + logger.LogError($"{item.Host}链接已关闭"); + } + } + catch (Exception ex) + { + logger.LogError($"{item.Host}发送数据出现异常:{ex}"); + } + } + else + { + if (item.TerminalNos.Contains(parameter.TerminalNo) && channeldic.TryGetValue($"{parameter.TerminalNo}_{item.Host}", out var clientChannel)) + { + try + { + if (clientChannel.Open) + { + if (logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) + logger.LogDebug($"转发{parameter.TerminalNo}到该网关{item.Host}"); + clientChannel.WriteAndFlushAsync(Unpooled.WrappedBuffer(parameter.Data)); + } + else + { + logger.LogError($"{item.Host},{parameter.TerminalNo}链接已关闭"); + } + } + catch (Exception ex) + { + logger.LogError($"{item.Host},{parameter.TerminalNo}发送数据出现异常:{ex}"); + } + } + } + } + } + } + + public void InitialDispatcherClient() + { + Task.Run(async () => + { + var group = new MultithreadEventLoopGroup(); + var bootstrap = new Bootstrap(); + bootstrap.Group(group) + .Channel() + .Option(ChannelOption.TcpNodelay, true) + .Handler(new ActionChannelInitializer(channel => + { + IChannelPipeline pipeline = channel.Pipeline; + pipeline.AddLast(new ClientConnectionHandler(bootstrap, channeldic, loggerFactory)); + })); + optionsMonitor.OnChange(options => + { + List lastRemoteServers = new List(); + if (options.DataTransfer != null) + { + if (options.DataTransfer.Any()) + { + foreach (var item in options.DataTransfer) + { + if (item.TerminalNos != null) + { + if (item.TerminalNos.Any()) + { + foreach (var terminal in item.TerminalNos) + { + lastRemoteServers.Add($"{terminal}_{item.Host}"); + } + } + else + { + lastRemoteServers.Add($"all_{item.Host}"); + } + } + else + { + lastRemoteServers.Add($"all_{item.Host}"); + } + } + } + } + DelRemoteServsers(lastRemoteServers); + AddRemoteServsers(bootstrap, lastRemoteServers); + }); + await InitRemoteServsers(bootstrap); + }); + } + /// + /// 初始化远程服务器 + /// + /// + /// + /// + private async Task InitRemoteServsers(Bootstrap bootstrap) + { + List remoteServers = new List(); + if (optionsMonitor.CurrentValue.DataTransfer != null) + { + if (optionsMonitor.CurrentValue.DataTransfer.Any()) + { + foreach (var item in optionsMonitor.CurrentValue.DataTransfer) + { + if (item.TerminalNos != null) + { + if (item.TerminalNos.Any()) + { + foreach (var terminal in item.TerminalNos) + { + remoteServers.Add($"{terminal}_{item.Host}"); + } + } + else + { + remoteServers.Add($"all_{item.Host}"); + } + } + else + { + remoteServers.Add($"all_{item.Host}"); + } + } + } + } + foreach (var item in remoteServers) + { + try + { + string ip_port = item.Split('_')[1]; + IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(ip_port.Split(':')[0]), int.Parse(ip_port.Split(':')[1]))); + channeldic.Add(item, clientChannel); + if (clientChannel.Open) + { + if (logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) + { + logger.LogDebug($"该终端{item.Replace("_", "已连接上该服务器")}"); + } + } + } + catch (Exception ex) + { + logger.LogError($"初始化配置链接远程服务端{item},链接异常:{ex}"); + } + } + await Task.CompletedTask; + } + /// + /// 动态删除远程服务器 + /// + /// + private void DelRemoteServsers(List lastRemoteServers) + { + var delChannels = channeldic.Keys.Except(lastRemoteServers).ToList(); + foreach (var item in delChannels) + { + channeldic[item].CloseAsync(); + channeldic.Remove(item); + } + } + /// + /// 动态添加远程服务器 + /// + /// + /// + private void AddRemoteServsers(Bootstrap bootstrap, List lastRemoteServers) + { + var addChannels = lastRemoteServers.Except(channeldic.Keys).ToList(); + foreach (var item in addChannels) + { + try + { + var ip_port = item.Split('_')[1]; + IChannel clientChannel = bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(ip_port.Split(':')[0]), int.Parse(ip_port.Split(':')[1]))).Result; + channeldic.Add(item, clientChannel); + if (clientChannel.Open) { + if (logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) + { + logger.LogDebug($"该终端{item.Replace("_", "已连接上该服务器")}"); + } + } + } + catch (Exception ex) + { + logger.LogError($"变更配置后链接远程服务端{item},重连异常:{ex}"); + } + } + } + } +} diff --git a/src/JT808.Gateway/Configurations/JT808ClientConfiguration.cs b/src/JT808.Gateway/Configurations/JT808ClientConfiguration.cs deleted file mode 100644 index 98bee22..0000000 --- a/src/JT808.Gateway/Configurations/JT808ClientConfiguration.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Text; - -namespace JT808.Gateway.Configurations -{ - public class JT808ClientConfiguration - { - public string Host { get; set; } - - public int Port { get; set; } - - private EndPoint endPoint; - - public EndPoint EndPoint - { - get - { - if (endPoint == null) - { - if (IPAddress.TryParse(Host, out IPAddress ip)) - { - endPoint = new IPEndPoint(ip, Port); - } - } - return endPoint; - } - } - } -} diff --git a/src/JT808.Gateway/Converters/JsonByteArrayHexConverter.cs b/src/JT808.Gateway/Converters/JsonByteArrayHexConverter.cs deleted file mode 100644 index f3b4a1c..0000000 --- a/src/JT808.Gateway/Converters/JsonByteArrayHexConverter.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JT808.Gateway.Converters -{ - class ByteArrayHexConverter : JsonConverter - { - public override bool CanConvert(Type objectType) => objectType == typeof(byte[]); - - public override bool CanRead => false; - public override bool CanWrite => true; - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) => throw new NotImplementedException(); - - private readonly string _separator; - - public ByteArrayHexConverter(string separator = " ") => _separator = separator; - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - var hexString = string.Join(_separator, ((byte[])value).Select(p => p.ToString("X2"))); - writer.WriteValue(hexString); - } - } -} diff --git a/src/JT808.Gateway/Converters/JsonIPAddressConverter.cs b/src/JT808.Gateway/Converters/JsonIPAddressConverter.cs deleted file mode 100644 index eb7c096..0000000 --- a/src/JT808.Gateway/Converters/JsonIPAddressConverter.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net; -using System.Text; - -namespace JT808.Gateway.Converters -{ - public class JsonIPAddressConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(IPAddress)); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - writer.WriteValue(value.ToString()); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - return IPAddress.Parse((string)reader.Value); - } - } -} diff --git a/src/JT808.Gateway/Converters/JsonIPEndPointConverter.cs b/src/JT808.Gateway/Converters/JsonIPEndPointConverter.cs deleted file mode 100644 index bed1864..0000000 --- a/src/JT808.Gateway/Converters/JsonIPEndPointConverter.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Net; - -namespace JT808.Gateway.Converters -{ - public class JsonIPEndPointConverter: JsonConverter - { - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(IPEndPoint)); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - IPEndPoint ep = (IPEndPoint)value; - JObject jo = new JObject(); - jo.Add("Host", JToken.FromObject(ep.Address, serializer)); - jo.Add("Port", ep.Port); - jo.WriteTo(writer); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - JObject jo = JObject.Load(reader); - IPAddress address = jo["Host"].ToObject(serializer); - int port = (int)jo["Port"]; - return new IPEndPoint(address, port); - } - } -} diff --git a/src/JT808.Gateway/Dtos/JT808AtomicCounterDto.cs b/src/JT808.Gateway/Dtos/JT808AtomicCounterDto.cs deleted file mode 100644 index 0fc1ae6..0000000 --- a/src/JT808.Gateway/Dtos/JT808AtomicCounterDto.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace JT808.Gateway.Dtos -{ - /// - /// 包计数器服务 - /// - public class JT808AtomicCounterDto - { - public long MsgSuccessCount { get; set; } - - public long MsgFailCount { get; set; } - } -} diff --git a/src/JT808.Gateway/Dtos/JT808DefaultResultDto.cs b/src/JT808.Gateway/Dtos/JT808DefaultResultDto.cs deleted file mode 100644 index f32ac0b..0000000 --- a/src/JT808.Gateway/Dtos/JT808DefaultResultDto.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace JT808.Gateway.Dtos -{ - public class JT808DefaultResultDto: JT808ResultDto - { - public JT808DefaultResultDto() - { - Data = "Hello,JT808 WebAPI"; - Code = JT808ResultCode.Ok; - } - } -} diff --git a/src/JT808.Gateway/Dtos/JT808IPAddressDto.cs b/src/JT808.Gateway/Dtos/JT808IPAddressDto.cs deleted file mode 100644 index 5fc9e2d..0000000 --- a/src/JT808.Gateway/Dtos/JT808IPAddressDto.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Runtime.Serialization; -using System.Text; - -namespace JT808.Gateway.Dtos -{ - public class JT808IPAddressDto - { - public string Host { get; set; } - - public int Port { get; set; } - - public EndPoint endPoint; - - public EndPoint EndPoint - { - get - { - if (endPoint == null) - { - if (IPAddress.TryParse(Host, out IPAddress ip)) - { - endPoint = new IPEndPoint(ip, Port); - } - else - { - endPoint = new DnsEndPoint(Host, Port); - } - } - return endPoint; - } - set { } - } - } -} diff --git a/src/JT808.Gateway/Dtos/JT808UnificationSendRequestDto.cs b/src/JT808.Gateway/Dtos/JT808UnificationSendRequestDto.cs deleted file mode 100644 index d15c29a..0000000 --- a/src/JT808.Gateway/Dtos/JT808UnificationSendRequestDto.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace JT808.Gateway.Dtos -{ - /// - /// 统一下发请求参数 - /// - public class JT808UnificationSendRequestDto - { - public string TerminalPhoneNo { get; set; } - public byte[] Data { get; set; } - } -} diff --git a/src/JT808.Gateway/Handlers/JT808MsgIdHttpHandlerBase.cs b/src/JT808.Gateway/Handlers/JT808MsgIdHttpHandlerBase.cs deleted file mode 100644 index 3343214..0000000 --- a/src/JT808.Gateway/Handlers/JT808MsgIdHttpHandlerBase.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using JT808.Gateway.Dtos; -using JT808.Gateway.Metadata; -using Newtonsoft.Json; - -namespace JT808.Gateway.Handlers -{ - /// - /// 基于webapi http模式抽象消息处理业务 - /// 自定义消息处理业务 - /// 注意: - /// 1.ConfigureServices: - /// services.Replace(new ServiceDescriptor(typeof(JT808MsgIdHttpHandlerBase),typeof(JT808MsgIdCustomHttpHandlerImpl),ServiceLifetime.Singleton)); - /// 2.解析具体的消息体,具体消息调用具体的JT808Serializer.Deserialize - /// - public abstract class JT808MsgIdHttpHandlerBase - { - /// - /// 初始化消息处理业务 - /// - protected JT808MsgIdHttpHandlerBase() - { - HandlerDict = new Dictionary>(); - } - - protected void CreateRoute(string url, Func func) - { - if (!HandlerDict.ContainsKey(url)) - { - HandlerDict.Add(url, func); - } - else - { - // 替换 - HandlerDict[url] = func; - } - } - - public Dictionary> HandlerDict { get; } - - protected JT808HttpResponse CreateJT808HttpResponse(dynamic dynamicObject) - { - byte[] data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(dynamicObject)); - return new JT808HttpResponse() - { - Data = data - }; - } - - public JT808HttpResponse DefaultHttpResponse() - { - byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808DefaultResultDto())); - return new JT808HttpResponse(json); - } - - public JT808HttpResponse EmptyHttpResponse() - { - byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808ResultDto() - { - Code = JT808ResultCode.Empty, - Message = "内容为空", - Data = "Content Empty" - })); - return new JT808HttpResponse(json); - } - - public JT808HttpResponse NotFoundHttpResponse() - { - byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808ResultDto() - { - Code = JT808ResultCode.NotFound, - Message = "没有该服务", - Data = "没有该服务" - })); - return new JT808HttpResponse(json); - } - - public JT808HttpResponse ErrorHttpResponse(Exception ex) - { - byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808ResultDto() - { - Code = JT808ResultCode.Error, - Message = JsonConvert.SerializeObject(ex), - Data = ex.Message - })); - return new JT808HttpResponse(json); - } - } -} diff --git a/src/JT808.Gateway/JT808.Gateway.csproj b/src/JT808.Gateway/JT808.Gateway.csproj index 7920245..ff7b4aa 100644 --- a/src/JT808.Gateway/JT808.Gateway.csproj +++ b/src/JT808.Gateway/JT808.Gateway.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netstandard2.0 8.0 Copyright 2018. SmallChi(Koike) @@ -14,12 +14,15 @@ false LICENSE true + JT808.Gateway + JT808.Gateway - + + @@ -32,8 +35,8 @@ - + diff --git a/src/JT808.Gateway/JT808GatewayExtensions.cs b/src/JT808.Gateway/JT808GatewayExtensions.cs index 73e44f7..17ed1b0 100644 --- a/src/JT808.Gateway/JT808GatewayExtensions.cs +++ b/src/JT808.Gateway/JT808GatewayExtensions.cs @@ -1,6 +1,5 @@ using JT808.Gateway; using JT808.Gateway.Configurations; -using JT808.Gateway.Converters; using JT808.Gateway.Impls; using JT808.Gateway.Interfaces; using JT808.Gateway.PubSub; @@ -11,47 +10,17 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; -using Newtonsoft.Json; using System; using System.Runtime.CompilerServices; -//[assembly: InternalsVisibleTo("JT808.DotNetty.Core.Test")] +[assembly: InternalsVisibleTo("JT808.Gateway.Test")] namespace JT808.Gateway { public static class JT808GatewayExtensions { - static JT808GatewayExtensions() + public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, IConfiguration configuration) { - JsonConvert.DefaultSettings = new Func(() => - { - Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings(); - //日期类型默认格式化处理 - settings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat; - settings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; - //空值处理 - settings.NullValueHandling = NullValueHandling.Ignore; - settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - settings.Converters.Add(new JsonIPAddressConverter()); - settings.Converters.Add(new JsonIPEndPointConverter()); - settings.Converters.Add(new ByteArrayHexConverter()); - return settings; - }); - } - - public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, IConfiguration configuration, Newtonsoft.Json.JsonSerializerSettings settings=null) - { - if (settings != null) - { - JsonConvert.DefaultSettings = new Func(() => - { - settings.Converters.Add(new JsonIPAddressConverter()); - settings.Converters.Add(new JsonIPEndPointConverter()); - settings.Converters.Add(new ByteArrayHexConverter()); - settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - return settings; - }); - } IJT808GatewayBuilder nettyBuilder = new JT808GatewayBuilderDefault(jt808Builder); nettyBuilder.JT808Builder.Services.Configure(configuration.GetSection("JT808Configuration")); nettyBuilder.JT808Builder.Services.TryAddSingleton(); @@ -66,19 +35,8 @@ namespace JT808.Gateway return nettyBuilder; } - public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, Action jt808Options, Newtonsoft.Json.JsonSerializerSettings settings = null) + public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, Action jt808Options) { - if (settings != null) - { - JsonConvert.DefaultSettings = new Func(() => - { - settings.Converters.Add(new JsonIPAddressConverter()); - settings.Converters.Add(new JsonIPEndPointConverter()); - settings.Converters.Add(new ByteArrayHexConverter()); - settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - return settings; - }); - } IJT808GatewayBuilder nettyBuilder = new JT808GatewayBuilderDefault(jt808Builder); nettyBuilder.JT808Builder.Services.Configure(jt808Options); nettyBuilder.JT808Builder.Services.TryAddSingleton(); diff --git a/src/JT808.Gateway/Services/JT808GatewayService.cs b/src/JT808.Gateway/Services/JT808GatewayService.cs index b89052a..9a97d18 100644 --- a/src/JT808.Gateway/Services/JT808GatewayService.cs +++ b/src/JT808.Gateway/Services/JT808GatewayService.cs @@ -35,15 +35,18 @@ namespace JT808.Gateway.Services { var result = jT808SessionService.GetTcpAll(); TcpSessionInfoReply reply = new TcpSessionInfoReply(); - foreach(var item in result.Data) + if (result.Data != null) { - reply.TcpSessions.Add(new SessionInfo + foreach (var item in result.Data) { - LastActiveTime= item.LastActiveTime.ToString("yyyy-MM-dd HH:mm:ss"), - StartTime= item.StartTime.ToString("yyyy-MM-dd HH:mm:ss"), - RemoteAddressIP= item.RemoteAddressIP, - TerminalPhoneNo=item.TerminalPhoneNo - }); + reply.TcpSessions.Add(new SessionInfo + { + LastActiveTime = item.LastActiveTime.ToString("yyyy-MM-dd HH:mm:ss"), + StartTime = item.StartTime.ToString("yyyy-MM-dd HH:mm:ss"), + RemoteAddressIP = item.RemoteAddressIP, + TerminalPhoneNo = item.TerminalPhoneNo + }); + } } return Task.FromResult(reply); } @@ -58,15 +61,18 @@ namespace JT808.Gateway.Services { var result = jT808SessionService.GetUdpAll(); UdpSessionInfoReply reply = new UdpSessionInfoReply(); - foreach (var item in result.Data) + if (result.Data != null) { - reply.UdpSessions.Add(new SessionInfo + foreach (var item in result.Data) { - LastActiveTime = item.LastActiveTime.ToString("yyyy-MM-dd HH:mm:ss"), - StartTime = item.StartTime.ToString("yyyy-MM-dd HH:mm:ss"), - RemoteAddressIP = item.RemoteAddressIP, - TerminalPhoneNo = item.TerminalPhoneNo - }); + reply.UdpSessions.Add(new SessionInfo + { + LastActiveTime = item.LastActiveTime.ToString("yyyy-MM-dd HH:mm:ss"), + StartTime = item.StartTime.ToString("yyyy-MM-dd HH:mm:ss"), + RemoteAddressIP = item.RemoteAddressIP, + TerminalPhoneNo = item.TerminalPhoneNo + }); + } } return Task.FromResult(reply); } diff --git a/src/JT808.Gateway/Services/JT808SessionService.cs b/src/JT808.Gateway/Services/JT808SessionService.cs index 5b140f4..f2ecb8c 100644 --- a/src/JT808.Gateway/Services/JT808SessionService.cs +++ b/src/JT808.Gateway/Services/JT808SessionService.cs @@ -36,7 +36,7 @@ namespace JT808.Gateway.Services { resultDto.Data = null; resultDto.Code = JT808ResultCode.Error; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); + resultDto.Message =ex.Message; } return resultDto; } @@ -59,7 +59,7 @@ namespace JT808.Gateway.Services { resultDto.Data = null; resultDto.Code = JT808ResultCode.Error; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); + resultDto.Message = ex.Message; } return resultDto; } @@ -84,13 +84,13 @@ namespace JT808.Gateway.Services { resultDto.Data = false; resultDto.Code = 500; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); + resultDto.Message = ex.Message; } catch (Exception ex) { resultDto.Data = false; resultDto.Code = JT808ResultCode.Error; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); + resultDto.Message = ex.Message; } return resultDto; } diff --git a/src/JT808.Gateway/Services/JT808UnificationSendService.cs b/src/JT808.Gateway/Services/JT808UnificationSendService.cs index cdecb14..d7d54e3 100644 --- a/src/JT808.Gateway/Services/JT808UnificationSendService.cs +++ b/src/JT808.Gateway/Services/JT808UnificationSendService.cs @@ -37,7 +37,7 @@ namespace JT808.Gateway.Services { resultDto.Data = false; resultDto.Code = JT808ResultCode.Error; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); + resultDto.Message = ex.Message; } return resultDto; } diff --git a/src/JT808.Gateway/Simples/JT808SimpleTcpClient.cs b/src/JT808.Gateway/Simples/JT808SimpleTcpClient.cs index 8887a27..34102ed 100644 --- a/src/JT808.Gateway/Simples/JT808SimpleTcpClient.cs +++ b/src/JT808.Gateway/Simples/JT808SimpleTcpClient.cs @@ -5,7 +5,7 @@ using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -namespace JT808.DotNetty.Core +namespace JT808.Gateway.Simples { internal class JT808SimpleTcpClient { diff --git a/src/JT808.Gateway/Simples/JT808SimpleUdpClient.cs b/src/JT808.Gateway/Simples/JT808SimpleUdpClient.cs index 568658f..67c3111 100644 --- a/src/JT808.Gateway/Simples/JT808SimpleUdpClient.cs +++ b/src/JT808.Gateway/Simples/JT808SimpleUdpClient.cs @@ -5,7 +5,7 @@ using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -namespace JT808.DotNetty.Core +namespace JT808.Gateway.Simples { internal class JT808SimpleUdpClient {