├── .gitignore ├── .idea ├── codeStyleSettings.xml └── copyright │ ├── ALv2.xml │ └── profiles_settings.xml ├── .travis.yml ├── LICENSE ├── README.md ├── SECURITY.md ├── apache-2.0.txt ├── circle.yml ├── docs ├── README.md └── index.md ├── findbugs-exlude.xml ├── mkdocs.yml ├── pmd-rule-production.xml ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── mbed │ │ └── example │ │ ├── EndpointContainer.java │ │ ├── MbedClientService.java │ │ ├── common │ │ └── string │ │ │ ├── HexArray.java │ │ │ └── Utf8String.java │ │ ├── data │ │ ├── EndpointMetadata.java │ │ ├── ResourceMetadata.java │ │ ├── ResourcePath.java │ │ ├── ResourceValue.java │ │ ├── ServerConfiguration.java │ │ └── tlv │ │ │ ├── LWM2MID.java │ │ │ ├── LWM2MObjectInstance.java │ │ │ ├── LWM2MResource.java │ │ │ ├── LWM2MResourceInstance.java │ │ │ ├── LWM2MResourceType.java │ │ │ ├── TLV.java │ │ │ └── TLVDeserializer.java │ │ └── resources │ │ ├── ConfigurationResource.java │ │ ├── EndpointsResource.java │ │ ├── MbedClientResource.java │ │ ├── SubscriptionResources.java │ │ └── WebApiService.java ├── resources │ └── log4j.properties └── webapp │ ├── Configuration.html │ ├── Devices.html │ ├── Resources.html │ ├── WEB-INF │ └── web.xml │ ├── css │ └── Custom.css │ ├── img │ ├── bg.jpg │ ├── connected.png │ ├── disconnected.png │ └── mbed-logo.png │ ├── js │ └── app │ │ ├── configurationModule │ │ ├── ConfigurationController.js │ │ ├── ConfigurationDirective.js │ │ ├── ConfigurationService.js │ │ └── app.js │ │ ├── deviceModule │ │ ├── DevicesController.js │ │ ├── DevicesService.js │ │ └── app.js │ │ └── resourceModule │ │ ├── ResourcesController.js │ │ ├── ResourcesDirective.js │ │ ├── ResourcesService.js │ │ └── app.js │ └── lib │ ├── angular-moment-v0.10.2 │ └── angular-moment.min.js │ ├── angularjs-v1.4.3 │ ├── angular-animate.js │ ├── angular-animate.min.js │ ├── angular-animate.min.js.map │ ├── angular-resource.js │ ├── angular-resource.min.js │ ├── angular-resource.min.js.map │ ├── angular.js │ ├── angular.min.js │ └── angular.min.js.map │ ├── bootstrap-v3.3.5 │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── moment-v2.10.6 │ └── moment.min.js │ └── x-editable-v1.5.1 │ ├── css │ └── bootstrap-editable.css │ ├── img │ ├── clear.png │ └── loading.gif │ └── js │ ├── bootstrap-editable.js │ └── bootstrap-editable.min.js └── test └── java └── org └── mbed └── example ├── EndpointContainerTest.java ├── MbedClientServiceTest.java └── resources ├── ConfigurationResourceTest.java ├── EndpointsResourceTest.java └── SubscriptionResourceTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .settings 4 | classes/ 5 | target/ 6 | log/ 7 | nbactions.xml 8 | .idea/* 9 | !.idea/codeStyleSettings.xml 10 | !.idea/copyright 11 | *.iml 12 | *.uml 13 | *.state 14 | *~ 15 | /nb-configuration.xml -------------------------------------------------------------------------------- /.idea/codeStyleSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 33 | 35 | -------------------------------------------------------------------------------- /.idea/copyright/ALv2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | 5 | script: "mvn clean install -P static-code-check" 6 | 7 | sudo: false -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Unless specifically indicated otherwise in a file, files are licensed 2 | under the Apache 2.0 license, as can be found in: apache-2.0.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | mbed web application - example 2 | ============================== 3 | 4 | This is a simple web application that connects to [mbed Device Connector Service](https://www.mbed.com/en/development/cloud/mbed-device-connector-service/). 5 | 6 | ### Features 7 | 8 | - Configure connection to mbed DS. 9 | - List all devices, 10 | - List device resources, 11 | - Invoke proxy requests (GET, PUT, POST, DELETE). 12 | 13 | ### REST Client (mbed Device Server Java Client) dependency 14 | 15 | The example app build has a dependency on mbed Device Server Java Client libraries (used for calling mbed Device Server HTTP REST API). The dependency is defined in the ``pom.xml`` file that you can use in your own web application to ease up and streamline development. 16 | 17 | The REST Client libraries can be found in the [http://maven.mbed.com](http://maven.mbed.com) repository, as defined in ``pom.xml``: 18 | 19 | ... 20 | 3.0.0-464 21 | ... 22 | 23 | com.mbed 24 | mbed-client 25 | ${mbed-client.version} 26 | 27 | 28 | com.mbed 29 | mbed-client-servlet 30 | ${mbed-client.version} 31 | 32 | 33 | javax.servlet-api 34 | javax.servlet 35 | 36 | 37 | 38 | ... 39 | 40 | 41 | mbed repository 42 | http://maven.mbed.com 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Development 54 | ----------- 55 | 56 | ### Requirements 57 | - Java 8 58 | - Maven 3.x 59 | - mbed DS - to which the example application connects. 60 | 61 | ### Build: 62 | 63 | mvn clean package 64 | 65 | With static code analyses check (findbugs, pmd, jacoco): 66 | 67 | mvn clean package -P static-code-check 68 | 69 | Build executable war (with embedded tomcat): 70 | 71 | mvn clean package tomcat7:exec-war-only 72 | 73 | ### Run 74 | - Jetty (embedded): 75 | 76 | mvn jetty:run 77 | 78 | - Tomcat (embedded): 79 | 80 | mvn tomcat7:run 81 | 82 | - Executable war (with embedded Tomcat): 83 | 84 | cd target 85 | java -Dcom.arm.mbed.restclient.servlet.server-port=8082 -jar example-app-1.0-SNAPSHOT-war-exec.jar -httpPort=8082 86 | 87 | Open from browser: http://localhost:8082 88 | 89 | Configuring with mbed Device Connector 90 | ============================== 91 | 92 | 1. Open [https://connector.mbed.com](https://connector.mbed.com) in your browser. 93 | 2. Log in with your credentials, or sign up to get credentials. 94 | 3. Click the **Access keys** link. 95 | 4. Create a new access key. 96 | 5. Copy the mbed DS address (https://api.connector.mbed.com) from this page. 97 | 6. Open the example-app in your browser: [http://localhost:8082](http://localhost:8082). 98 | 7. Select the **Configuration** tab at the top of the page. 99 | 8. Select **Token Authentication**. 100 | 9. Enter the access key and the copied mbed DS address. 101 | 10. Select the Pull or Push notification channel. Pull is recommended. Push Notifications require a publicly available URL for the example app (example value: http://REMOTE_HOST:8082/mds-notif). 102 | 11. Save. 103 | 104 | Pre-subscription 105 | ============================== 106 | 107 | The mbed Device Server (mbed DS) eventing model consists of observable resources, which enables endpoints to deliver updated resource content, periodically or with a more sophisticated solution-dependent logic. 108 | 109 | Applications can subscribe to every individual resource, or set pre-subscription data to receive a notification update. 110 | 111 | Pre-subscription is an advanced feature supported by mbed Device Server (mbed DS) along with the basic subscription feature. Pre-subscription allows an application to define a set of rules and patterns put by the application. When an endpoint registers and its name, type or registered resources match the pre-subscription data, mbed DS sends subscription requests to the device automatically. 112 | 113 | The pre-subscription handles all the endpoints that are already registered and the server sends subscription requests to the devices as soon as the patterns are set. 114 | 115 | To use pre-subscription: 116 | 117 | 1. Open the example-app in your browser: [http://localhost:8082](http://localhost:8082). 118 | 2. Select the **Configuration** tab at the top of the page. 119 | 3. Select the **Pre-Subscription** tab in the page. 120 | 4. Set the pre-subscription pattern by: 121 | - The pattern may include the **endpoint name** (optionally having an ``*`` character at the end), **endpoint type**, a list of **resources** or expressions with an ``*`` character at the end. 122 | 123 | _Example_ 124 | 125 | endpoint-type: "Light", 126 | resource-path: ["/sen/*"] 127 | 128 | 5. Click **ADD** to create the pattern. 129 | 6. Click **delete** to delete the pattern. 130 | 7. Click **edit** to edit the pattern. 131 | 8. When you are ready to save your pre-subscription patterns, click **SAVE**. 132 | - Changing the pre-subscription data overwrites the previous subscriptions. To remove the pre-subscription data, put an empty array as a rule. 133 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /apache-2.0.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | java: 3 | version: oraclejdk8 4 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | mbed Web Application - Example 2 | ============================== 3 | 4 | ## Features 5 | 6 | - Configure connection to mbed Device Server (mbed DS). 7 | - List all devices. 8 | - List device resources. 9 | - Invoke proxy requests (GET, PUT, POST, DELETE). 10 | 11 | ## REST Client (mbed Device Server Java Client) dependency 12 | 13 | The example app build has a dependency on mbed Device Server Java Client libraries (used for calling mbed Device Server HTTP REST API). The dependency is defined in the `pom.xml` file that you can use in your own 14 | web application to ease up and streamline development. 15 | 16 | The REST Client libraries can be found in http://maven.mbed.com repository as defined in `pom.xml`: 17 | 18 | ... 19 | 3.0.0-464 20 | ... 21 | 22 | com.mbed 23 | mbed-client 24 | ${mbed-client.version} 25 | 26 | 27 | com.mbed 28 | mbed-client-servlet 29 | ${mbed-client.version} 30 | 31 | 32 | javax.servlet-api 33 | javax.servlet 34 | 35 | 36 | 37 | ... 38 | 39 | 40 | mbed repository 41 | http://maven.mbed.com 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | ## Requirements 53 | - Java 8 54 | - Maven 3.x 55 | - mbed DS - to which the example application connects. 56 | 57 | ## Build: 58 | 59 | mvn clean package 60 | 61 | With static code analyses check (findbugs, pmd, jacoco): 62 | 63 | mvn clean package -P static-code-check 64 | 65 | Build executable war (with embedded tomcat): 66 | 67 | mvn clean package tomcat7:exec-war-only 68 | 69 | ## Run 70 | - Jetty (embedded): 71 | 72 | mvn jetty:run 73 | 74 | - Tomcat (embedded): 75 | 76 | mvn tomcat7:run 77 | 78 | - Executable war (with embedded Tomcat): 79 | 80 | cd target 81 | java -Dcom.arm.mbed.restclient.servlet.server-port=8082 -jar example-app-1.0-SNAPSHOT-war-exec.jar -httpPort=8082 82 | 83 | Open from browser: http://localhost:8082 84 | 85 | Configuring with mbed Device Connector 86 | ============================== 87 | 88 | 1. Open https://connector.mbed.com in your browser 89 | 2. Log in with your credentials, or sign up to get credentials. 90 | 3. Click the **Access keys** link. 91 | 4. Create new access key. 92 | 5. Copy the mbed DS address (https://api.connector.mbed.com) from this page. 93 | 6. Open the example-app in browser: http://localhost:8082. 94 | 7. Select **Configuration** tab at the top of the page. 95 | 8. Select **Token Authentication**. 96 | 9. Enter the access key and the copied mbed DS address. 97 | 10. Select Pull or Push notification channel. Pull is recommended. Push Notifications requires publicly available URL for the example app (example value: http://REMOTE_HOST:8082/mds-notif) 98 | 11. Save. 99 | 100 | Pre-subscription 101 | ============================== 102 | 103 | The mbed Device Server (mbed DS) eventing model consists of observable resources, which enables endpoints to deliver updated resource content, periodically or with a more sophisticated solution dependent logic. 104 | Applications can subscribe to every individual resource or set a pre-subscription data to receive a notification update. 105 | 106 | Pre-subscription is an advanced feature supported by mbed DS along with the basic subscription feature. Pre-subscription allows an application to define a set of rules and patterns put 107 | by the application. When an endpoint registers and its name, type or registered resources match the pre-subscription data, mbed DS sends subscription requests to the device automatically. 108 | The pre-subscription concerns all the endpoints that are already registered and the server sends subscription requests to the devices as soon as the patterns are set. 109 | 110 | 1. Open the example-app in your browser: http://localhost:8082. 111 | 2. Select **Configuration** tab at the top of the page. 112 | 3. Select **Pre-Subscription** tab in the page. 113 | 4. Set the Pre-subscription pattern: 114 | - The pattern may include the endpoint name (optionally having an `*` character at the end), endpoint type, a list of resources or expressions with an `*` character at the end. 115 | 116 | _Example_ 117 | 118 | endpoint-type: "Light", 119 | resource-path: ["/sen/*"] 120 | 121 | 5. Click **ADD** to create the pattern. 122 | 6. Click **delete** to delete the pattern. 123 | 7. Click **edit** to edit the pattern. 124 | 8. When you are ready to save your pre-subscription patterns, click **SAVE**. 125 | - Changing the pre-subscription data overwrites the previous subscriptions. To remove the pre-subscription data, put an empty array as a rule. 126 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ARM mbed Web Application 2 | ======================== 3 | 4 | This is a simple web application that connects to [mbed Device Server (mbed DS)](https://www.mbed.com/en/development/cloud/mbed-device-server/) and 5 | [mbed Device Connector Service](https://www.mbed.com/en/development/cloud/mbed-device-connector-service/). -------------------------------------------------------------------------------- /findbugs-exlude.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: ARM mbed Web Application Example 2 | theme: readthedocs 3 | use directory_urls: false 4 | pages: 5 | - ['index.md','ARM mbed Web Application'] 6 | - ['README.md','Quick guide to the example application','mbed Web Application'] 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /pmd-rule-production.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | 20 | 23 | 24 | pmd-rule-main.xml 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 54 | 55 | 56 | 57 | 58 | 59 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 4.0.0 22 | 23 | org.mbed.example.webapp 24 | example-app 25 | war 26 | 1.0-SNAPSHOT 27 | example-app 28 | 29 | 30 | 2.18 31 | UTF-8 32 | 3.0.3-4 33 | false 34 | 35 | 36 | 37 | 38 | 39 | org.apache.maven.plugins 40 | maven-compiler-plugin 41 | 3.2 42 | true 43 | 44 | 1.8 45 | 1.8 46 | 1.8 47 | 1.8 48 | 49 | 50 | 51 | org.eclipse.jetty 52 | jetty-maven-plugin 53 | 9.3.1.v20150714 54 | 55 | 10 56 | 57 | 58 | 59 | 60 | 8082 61 | 62 | 63 | 64 | com.arm.mbed.restclient.servlet.server-port 65 | 8082 66 | 67 | 68 | 69 | 70 | 71 | org.apache.tomcat.maven 72 | tomcat7-maven-plugin 73 | 74 | 2.1 75 | 76 | 8082 77 | 78 | 8082 79 | 80 | / 81 | 82 | 83 | 84 | org.codehaus.mojo 85 | findbugs-maven-plugin 86 | 3.0.1 87 | 88 | Max 89 | Normal 90 | true 91 | findbugs-exlude.xml 92 | false 93 | 94 | 95 | 96 | org.apache.maven.plugins 97 | maven-pmd-plugin 98 | 3.5 99 | 100 | 101 | pmd-rule-production.xml 102 | 103 | false 104 | 105 | 106 | 107 | org.jacoco 108 | jacoco-maven-plugin 109 | 0.7.5.201505241946 110 | 111 | 112 | 113 | BUNDLE 114 | 115 | 116 | INSTRUCTION 117 | COVEREDRATIO 118 | 0.55 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | org.glassfish.jersey 132 | jersey-bom 133 | ${jersey.version} 134 | pom 135 | import 136 | 137 | 138 | 139 | 140 | 141 | 142 | junit 143 | junit 144 | 4.11 145 | test 146 | 147 | 148 | org.assertj 149 | assertj-core 150 | 3.1.0 151 | test 152 | 153 | 154 | 155 | 156 | org.slf4j 157 | slf4j-api 158 | 1.7.5 159 | 160 | 161 | org.slf4j 162 | slf4j-log4j12 163 | 1.7.5 164 | 165 | 166 | log4j 167 | log4j 168 | 1.2.17 169 | 170 | 171 | log4j 172 | apache-log4j-extras 173 | 1.1 174 | 175 | 176 | org.mockito 177 | mockito-all 178 | 1.10.19 179 | test 180 | 181 | 182 | 183 | com.mbed 184 | mbed-client 185 | ${mbed-client.version} 186 | 187 | 188 | com.mbed 189 | mbed-client-servlet 190 | ${mbed-client.version} 191 | 192 | 193 | javax.servlet-api 194 | javax.servlet 195 | 196 | 197 | 198 | 199 | org.glassfish.jersey.containers 200 | jersey-container-servlet 201 | 202 | 203 | org.glassfish.jersey.media 204 | jersey-media-json-jackson 205 | 206 | 207 | com.google.code.gson 208 | gson 209 | 2.3.1 210 | 211 | 212 | 213 | 214 | 215 | jenkins 216 | 217 | 218 | env.BUILD_NUMBER 219 | 220 | 221 | 222 | 223 | 224 | org.jacoco 225 | jacoco-maven-plugin 226 | 227 | 228 | default-prepare-agent 229 | 230 | prepare-agent 231 | 232 | 233 | 234 | default-report 235 | prepare-package 236 | 237 | report 238 | 239 | 240 | 241 | 242 | 243 | org.codehaus.mojo 244 | findbugs-maven-plugin 245 | 246 | 247 | 248 | check 249 | 250 | 251 | 252 | 253 | 254 | org.apache.maven.plugins 255 | maven-pmd-plugin 256 | 257 | 258 | package 259 | 260 | pmd 261 | cpd 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | static-code-check 271 | 272 | 273 | 274 | org.jacoco 275 | jacoco-maven-plugin 276 | 277 | 278 | default-prepare-agent 279 | 280 | prepare-agent 281 | 282 | 283 | 284 | default-report 285 | prepare-package 286 | 287 | report 288 | 289 | 290 | 291 | default-check 292 | 293 | check 294 | 295 | 296 | 297 | 298 | 299 | org.codehaus.mojo 300 | findbugs-maven-plugin 301 | 302 | 303 | 304 | check 305 | 306 | 307 | 308 | 309 | 310 | org.apache.maven.plugins 311 | maven-pmd-plugin 312 | 313 | 314 | package 315 | 316 | check 317 | cpd-check 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | mbed repository 330 | http://maven.mbed.com 331 | 332 | true 333 | 334 | 335 | false 336 | 337 | 338 | 339 | 340 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/EndpointContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.mbed.example; 18 | 19 | import com.arm.mbed.restclient.entity.Endpoint; 20 | import com.arm.mbed.restclient.entity.EndpointResponse; 21 | import com.arm.mbed.restclient.entity.ResourceDescription; 22 | import com.arm.mbed.restclient.entity.notification.EndpointDescription; 23 | import com.arm.mbed.restclient.entity.notification.ResourceInfo; 24 | import com.arm.mbed.restclient.entity.notification.ResourceNotification; 25 | import java.util.Collection; 26 | import java.util.HashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | import java.util.concurrent.ConcurrentHashMap; 30 | import java.util.concurrent.atomic.AtomicBoolean; 31 | import java.util.stream.Collectors; 32 | import org.mbed.example.common.string.Utf8String; 33 | import org.mbed.example.data.ResourcePath; 34 | import org.mbed.example.data.ResourceValue; 35 | import org.mbed.example.data.tlv.LWM2MObjectInstance; 36 | import org.mbed.example.data.tlv.LWM2MResource; 37 | import org.mbed.example.data.tlv.TLV; 38 | import org.mbed.example.data.tlv.TLVDeserializer; 39 | import org.mbed.example.resources.EndpointsResource; 40 | import org.slf4j.LoggerFactory; 41 | 42 | /** 43 | * Created by mitvah01 on 15.7.2015. 44 | */ 45 | public class EndpointContainer { 46 | private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(EndpointsResource.class); 47 | private final Map endpointsList = new ConcurrentHashMap<>(); 48 | private final Map endpointResourceValues = new ConcurrentHashMap<>(); 49 | 50 | public Collection getAllEndpoints() { 51 | return endpointsList.values(); 52 | } 53 | 54 | public void putEndpoints(EndpointDescription[] endpoints) { 55 | for (EndpointDescription endpointDescription : endpoints) { 56 | endpointsList.put(endpointDescription.getName(), endpointDescription); 57 | } 58 | } 59 | 60 | public void removeEndpoints(String[] endpointsRemoved) { 61 | for (String endpoint : endpointsRemoved) { 62 | endpointsList.remove(endpoint); 63 | } 64 | } 65 | 66 | public void updateEndpointsList(List endpoints) { 67 | endpointsList.clear(); 68 | for (Endpoint ep : endpoints) { 69 | endpointsList.put(ep.getName(), new EndpointDescription(ep.getName(), ep.getType(), ep.isQueueMode(), null)); 70 | } 71 | } 72 | 73 | public boolean updateResource(ResourcePath resourcePath, boolean isWaitingForResponse) { 74 | final AtomicBoolean success = new AtomicBoolean(true); 75 | endpointResourceValues.compute(resourcePath, (resourcePath1, old) -> { 76 | if (old != null) { 77 | if (old.isWaitingForResponse()) { 78 | success.set(false); 79 | return old; 80 | } 81 | return new ResourceValue(old.getValue(), isWaitingForResponse, 0, null, null, 0, false); 82 | } else { 83 | return new ResourceValue(null, isWaitingForResponse, 0, null, null, 0, false); 84 | } 85 | }); 86 | return success.get(); 87 | } 88 | 89 | public void updateResource(ResourcePath resourcePath, EndpointResponse response) { 90 | endpointResourceValues.put(resourcePath, new ResourceValue(getAndCheckPayloadForTlv(response), false, response.getStatus(), null, response.getContentType(), response.getMaxAge(), false)); 91 | } 92 | 93 | private String getAndCheckPayloadForTlv(EndpointResponse response) { 94 | String contentType = response.getContentType(); 95 | if (contentType != null && contentType.equals(TLV.CT_APPLICATION_LWM2M_TLV) && response.getPayload().length > 0) { 96 | StringBuilder payload = new StringBuilder(); 97 | 98 | if(TLVDeserializer.isObjectInstance(response.getPayload())){ 99 | List objectInstances = TLVDeserializer.deserialiseObjectInstances(response.getPayload()); 100 | payload.append(objectInstances.stream() 101 | .map(LWM2MObjectInstance::toString) 102 | .collect(Collectors.joining("\r\n"))); 103 | }else if(TLVDeserializer.isResource(response.getPayload()) || TLVDeserializer.isMultipleResource(response.getPayload())){ 104 | List resources = TLVDeserializer.deserializeResources(response.getPayload()); 105 | payload.append(resources.stream() 106 | .map(LWM2MResource::toString) 107 | .collect(Collectors.joining("\r\n"))); 108 | }else{ 109 | payload.append(response.getPayloadAsString()); 110 | } 111 | return payload.toString(); 112 | } else { 113 | return response.getPayloadAsString(); 114 | } 115 | } 116 | 117 | public void updateResource(ResourcePath resourcePath, ResourceNotification notification) { 118 | endpointResourceValues.put(resourcePath, new ResourceValue(Utf8String.from(notification.getPayload()), false, 200, null, notification.getContentType(), (int) notification.getMaxAge(), true)); 119 | } 120 | 121 | public void updateResource(ResourcePath resourcePath, EndpointResponse response, String value) { 122 | String payloadAsString = getAndCheckPayloadForTlv(response); 123 | if (payloadAsString != null && !payloadAsString.isEmpty()) { 124 | if (response.getStatus()==200) { 125 | endpointResourceValues.put(resourcePath, new ResourceValue(payloadAsString, false, response.getStatus(), null, response.getContentType(), response.getMaxAge(), false)); 126 | } else { 127 | endpointResourceValues.put(resourcePath, new ResourceValue(null, false, response.getStatus(), payloadAsString, response.getContentType(), response.getMaxAge(), false)); 128 | } 129 | } else { 130 | endpointResourceValues.put(resourcePath, new ResourceValue(value, false, response.getStatus(), null, response.getContentType(), response.getMaxAge(), false)); 131 | } 132 | } 133 | 134 | public void updateResource(ResourcePath resourcePath, String errorMessage) { 135 | endpointResourceValues.put(resourcePath, new ResourceValue(null, false, 0, errorMessage, null, 0, false)); 136 | } 137 | public Map getEndpointResourceValues(String endpointName) { 138 | EndpointDescription endpointDescription = endpointsList.get(endpointName); 139 | if (endpointDescription == null) { 140 | LOGGER.warn("Endpoint " + endpointName + " is missing"); 141 | return null; 142 | } 143 | if (endpointDescription.getResources() == null) { 144 | LOGGER.warn("Resource list is missing, nothing to return. [Endpoint name: " + endpointName + "]"); 145 | return null; 146 | } 147 | 148 | Map valueMap = new HashMap<>(); 149 | for (ResourceInfo resource : endpointDescription.getResources()) { 150 | ResourcePath resourcePath = new ResourcePath(endpointName, resource.getPath()); 151 | ResourceValue resourceValue = endpointResourceValues.get(resourcePath); 152 | if (resourceValue != null) { 153 | valueMap.put(resourcePath, resourceValue); 154 | } 155 | } 156 | return valueMap; 157 | } 158 | 159 | public EndpointDescription getEndpoint(String name) { 160 | return this.endpointsList.get(name); 161 | } 162 | 163 | public ResourceInfo[] updateResourceList(String epName, List resourceList) { 164 | ResourceInfo[] resources = resourceList.stream().map(resourceDescription -> 165 | new ResourceInfo(resourceDescription.getUriPath(), resourceDescription.getInterfaceDescription(), resourceDescription.getResourceType(), 166 | resourceDescription.getType(), resourceDescription.isObservable())).collect(Collectors.toList()).toArray(new ResourceInfo[resourceList.size()]); 167 | 168 | EndpointDescription endpointDescription = endpointsList.compute(epName, (s, old) -> { 169 | if (old != null) { 170 | LOGGER.trace("Updated resources for endpoint: {}", epName); 171 | return new EndpointDescription(old.getName(), old.getType(), old.getQueueMode(), resources); 172 | } 173 | return null; 174 | }); 175 | if (endpointDescription != null) { 176 | return endpointDescription.getResources(); 177 | } else { 178 | return null; 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/MbedClientService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.mbed.example; 18 | 19 | import com.arm.mbed.restclient.MbedClient; 20 | import com.arm.mbed.restclient.MbedClientBuilder; 21 | import com.arm.mbed.restclient.MbedClientInitializationException; 22 | import com.arm.mbed.restclient.MbedClientRuntimeException; 23 | import com.arm.mbed.restclient.NotificationListener; 24 | import com.arm.mbed.restclient.entity.notification.EndpointDescription; 25 | import com.arm.mbed.restclient.entity.notification.ResourceNotification; 26 | import com.arm.mbed.restclient.servlet.HttpServletChannel; 27 | import java.net.InetSocketAddress; 28 | import java.net.URI; 29 | import java.net.URISyntaxException; 30 | import javax.inject.Inject; 31 | import javax.inject.Singleton; 32 | import javax.ws.rs.Path; 33 | import org.mbed.example.data.ResourcePath; 34 | import org.mbed.example.data.ServerConfiguration; 35 | import org.slf4j.LoggerFactory; 36 | 37 | /** 38 | * @author szymon 39 | */ 40 | @Singleton 41 | @Path("mbed-client-service") //it's a DI hack 42 | public class MbedClientService { 43 | 44 | private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(MbedClientService.class); 45 | public static final ServerConfiguration DEFAULT_SERVER_CONFIGURATION = new ServerConfiguration("http://localhost:8080", "domain/app2", "secret", null, null); 46 | private MbedClient client; 47 | private boolean connected; 48 | private EndpointContainer endpointContainer; 49 | 50 | @Inject 51 | public MbedClientService() { 52 | this(null); 53 | } 54 | 55 | public MbedClientService(MbedClient mbedClient) { 56 | this.endpointContainer = new EndpointContainer(); 57 | if (mbedClient != null) { 58 | this.client = mbedClient; 59 | this.connected = true; 60 | } else { 61 | try { 62 | createConnection(DEFAULT_SERVER_CONFIGURATION); 63 | } catch (MbedClientInitializationException | URISyntaxException | MbedClientRuntimeException e) { 64 | LOGGER.warn("Cannot create connection:" + e.getMessage()); 65 | } catch (RuntimeException ex) { 66 | LOGGER.error("Unable to invoke client request: " + ex.getMessage()); 67 | } 68 | } 69 | } 70 | 71 | public void createConnection(ServerConfiguration configuration) throws MbedClientInitializationException, URISyntaxException { 72 | createConnection(configuration.getAddress(), configuration.getUsername(), configuration.getPassword(), configuration.getToken(), configuration.getPushurl()); 73 | } 74 | 75 | public void createConnection(String address, String clientName, String clientSecret, String token, String pushURL) throws MbedClientInitializationException, URISyntaxException { 76 | connected = false; 77 | if (client != null) { 78 | try { 79 | client.close(); 80 | } catch (Exception e) { 81 | LOGGER.warn("Connection did not close properly: " + e.getMessage()); 82 | } 83 | } 84 | boolean isSecure = false; 85 | URI uri = new URI(address); 86 | if (uri.getScheme().equals("https")) { 87 | isSecure = true; 88 | } 89 | int port = checkPort(uri.getPort(),isSecure); 90 | 91 | this.endpointContainer = new EndpointContainer(); 92 | HttpServletChannel httpServletChannel = null; 93 | boolean usePush = false; 94 | if (pushURL != null && !pushURL.isEmpty()) { 95 | usePush = true; 96 | httpServletChannel = new HttpServletChannel(pushURL, 30, 2000); 97 | } 98 | 99 | if (token != null && !token.isEmpty()) { 100 | createClientWithToken(usePush, isSecure, token, httpServletChannel, uri, port); 101 | } else { 102 | createClientWithBasicAuth(clientName, usePush, isSecure, clientSecret, httpServletChannel, uri, port); 103 | } 104 | readAllEndpoints(); 105 | connected = true; 106 | } 107 | 108 | private void createClientWithBasicAuth(String clientName, boolean usePush, boolean isSecure, String clientSecret, HttpServletChannel httpServletChannel, URI uri, int port) throws MbedClientInitializationException { 109 | if (clientName.split("/").length != 2) { 110 | throw new MbedClientInitializationException("Invalid user credentials"); 111 | } 112 | if (usePush) { 113 | if (isSecure) { 114 | this.client = MbedClientBuilder.newBuilder().credentials(clientName, clientSecret) 115 | .secure() 116 | .notifChannel(httpServletChannel) 117 | .notifListener(new NotificationListenerImpl(endpointContainer)).build(new InetSocketAddress(uri.getHost(), port)); 118 | } else { 119 | this.client = MbedClientBuilder.newBuilder().credentials(clientName, clientSecret) 120 | .notifChannel(httpServletChannel) 121 | .notifListener(new NotificationListenerImpl(endpointContainer)).build(new InetSocketAddress(uri.getHost(), port)); 122 | } 123 | } else { 124 | if (isSecure) { 125 | this.client = MbedClientBuilder.newBuilder().credentials(clientName, clientSecret) 126 | .secure() 127 | .notifChannelLongPolling() 128 | .notifListener(new NotificationListenerImpl(endpointContainer)).build(new InetSocketAddress(uri.getHost(), port)); 129 | } else { 130 | this.client = MbedClientBuilder.newBuilder().credentials(clientName, clientSecret) 131 | .notifChannelLongPolling() 132 | .notifListener(new NotificationListenerImpl(endpointContainer)).build(new InetSocketAddress(uri.getHost(), port)); 133 | } 134 | } 135 | } 136 | 137 | private void createClientWithToken(boolean usePush, boolean isSecure, String token, HttpServletChannel httpServletChannel, URI uri, int port) throws MbedClientInitializationException { 138 | if (usePush) { 139 | if (isSecure) { 140 | this.client = MbedClientBuilder.newBuilder().credentials(token) 141 | .secure() 142 | .notifChannel(httpServletChannel) 143 | .notifListener(new NotificationListenerImpl(endpointContainer)).build(new InetSocketAddress(uri.getHost(), port)); 144 | } else { 145 | this.client = MbedClientBuilder.newBuilder().credentials(token) 146 | .notifChannel(httpServletChannel) 147 | .notifListener(new NotificationListenerImpl(endpointContainer)).build(new InetSocketAddress(uri.getHost(), port)); 148 | } 149 | } else { 150 | if (isSecure) { 151 | this.client = MbedClientBuilder.newBuilder().credentials(token) 152 | .secure() 153 | .notifChannelLongPolling() 154 | .notifListener(new NotificationListenerImpl(endpointContainer)).build(new InetSocketAddress(uri.getHost(), port)); 155 | } else { 156 | this.client = MbedClientBuilder.newBuilder().credentials(token) 157 | .notifChannelLongPolling() 158 | .notifListener(new NotificationListenerImpl(endpointContainer)).build(new InetSocketAddress(uri.getHost(), port)); 159 | } 160 | } 161 | } 162 | 163 | int checkPort(int port, boolean isSecure) { 164 | return port == -1 ? (isSecure ? 443 : 80) : port; 165 | } 166 | 167 | public MbedClient client() { 168 | return client; 169 | } 170 | 171 | public boolean isConnected() { 172 | return connected; 173 | } 174 | 175 | public void readAllEndpoints() { 176 | endpointContainer.updateEndpointsList(client.endpoints().readAll()); 177 | } 178 | 179 | public EndpointContainer endpointContainer() { 180 | return this.endpointContainer; 181 | } 182 | 183 | static class NotificationListenerImpl implements NotificationListener { 184 | 185 | private final EndpointContainer endpointContainer; 186 | 187 | NotificationListenerImpl(EndpointContainer endpointContainer) { 188 | this.endpointContainer = endpointContainer; 189 | } 190 | 191 | @Override 192 | public void onEndpointsRegistered(EndpointDescription[] endpoints) { 193 | endpointContainer.putEndpoints(endpoints); 194 | } 195 | 196 | @Override 197 | public void onEndpointsUpdated(EndpointDescription[] endpoints) { 198 | endpointContainer.putEndpoints(endpoints); 199 | } 200 | 201 | @Override 202 | public void onEndpointsRemoved(String[] endpointsRemoved) { 203 | endpointContainer.removeEndpoints(endpointsRemoved); 204 | } 205 | 206 | @Override 207 | public void onResourcesUpdated(ResourceNotification[] resourceNotifications) { 208 | for (ResourceNotification notification : resourceNotifications) { 209 | ResourcePath resourcePath = new ResourcePath(notification.getEndpointName(), notification.getUriPath()); 210 | endpointContainer.updateResource(resourcePath, notification); 211 | } 212 | } 213 | 214 | @Override 215 | public void onEndpointsExpired(String[] endpointsExpired) { 216 | endpointContainer.removeEndpoints(endpointsExpired); 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/common/string/HexArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.common.string; 19 | 20 | import java.io.Serializable; 21 | import java.util.Arrays; 22 | 23 | /** 24 | * Utility class to convert byte array to string. 25 | */ 26 | public final class HexArray implements Serializable { 27 | 28 | private final static String HEX_DIGIT_STRING = "0123456789abcdef"; 29 | private final static char[] HEX_DIGITS = HEX_DIGIT_STRING.toCharArray(); 30 | private final byte[] data; 31 | 32 | /** 33 | * Converts byte array to hex string. 34 | * 35 | * @param data byte array data 36 | * @return hex string 37 | */ 38 | public static String toHex(final byte[] data) { 39 | return data != null ? toHex(data, data.length) : null; 40 | } 41 | 42 | /** 43 | * Converts byte array to hex string. 44 | * 45 | * @param data byte array data 46 | * @param len byte array length 47 | * @return hex string 48 | */ 49 | private static String toHex(final byte[] data, final int len) { 50 | final char[] retVal = new char[len * 2]; 51 | int k = 0; 52 | for (int i = 0; i < len; i++) { 53 | retVal[k++] = HEX_DIGITS[(data[i] & 0xf0) >>> 4]; 54 | retVal[k++] = HEX_DIGITS[data[i] & 0x0f]; 55 | } 56 | return new String(retVal); 57 | } 58 | 59 | public HexArray(byte... data) { 60 | this.data = data; 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return toHex(data, data.length); 66 | } 67 | 68 | @Override 69 | public boolean equals(Object obj) { 70 | if (obj == null) { 71 | return false; 72 | } 73 | if (getClass() != obj.getClass()) { 74 | return false; 75 | } 76 | final HexArray other = (HexArray) obj; 77 | return Arrays.equals(this.data, other.data); 78 | } 79 | 80 | @Override 81 | public int hashCode() { 82 | int hash = 3; 83 | hash = 17 * hash + Arrays.hashCode(this.data); 84 | return hash; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/common/string/Utf8String.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.common.string; 19 | 20 | import java.nio.charset.Charset; 21 | 22 | /** 23 | * Created by mitvah01 on 12.8.2015. 24 | */ 25 | public class Utf8String { 26 | public static String from(byte[] bytes) { 27 | if(isAscii(bytes)) { 28 | return new String(bytes, Charset.forName("UTF-8")); 29 | } else { 30 | return "0x" + HexArray.toHex(bytes); 31 | } 32 | } 33 | 34 | public static String from(int... bytes) { 35 | byte[] byteArray = new byte[bytes.length]; 36 | for (int i = 0; i < bytes.length; i++) { 37 | byteArray[i] = (byte) bytes[i]; 38 | } 39 | return from(byteArray); 40 | } 41 | 42 | private static boolean isAscii(byte[] bytes) { 43 | for (byte aByte : bytes) { 44 | if (aByte < 32 || aByte > 126) { 45 | return false; 46 | } 47 | } 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/EndpointMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.mbed.example.data; 18 | 19 | import com.arm.mbed.restclient.entity.notification.EndpointDescription; 20 | 21 | /** 22 | * @author szymon 23 | */ 24 | public class EndpointMetadata { 25 | private final String name; 26 | private final String type; 27 | 28 | EndpointMetadata(String name, String type) { 29 | this.name = name; 30 | this.type = type; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public String getType() { 38 | return type; 39 | } 40 | 41 | public static EndpointMetadata from(EndpointDescription ep) { 42 | return new EndpointMetadata(ep.getName(), ep.getType()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/ResourceMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.mbed.example.data; 18 | 19 | import com.arm.mbed.restclient.entity.notification.ResourceInfo; 20 | 21 | /** 22 | * Created by mitvah01 on 14.7.2015. 23 | */ 24 | public final class ResourceMetadata { 25 | private final String uri; 26 | private final String rt; 27 | private final String ifDesc; 28 | private final String type; 29 | private final boolean obs; 30 | private final boolean isSubscribed; 31 | 32 | public ResourceMetadata(String uri, String rt, String ifDesc, String type, boolean obs, boolean isSubscribed) { 33 | this.uri = uri; 34 | this.rt = rt; 35 | this.ifDesc = ifDesc; 36 | this.type = type; 37 | this.obs = obs; 38 | this.isSubscribed = isSubscribed; 39 | } 40 | 41 | public String getRt() { 42 | return rt; 43 | } 44 | 45 | public String getIfDesc() { 46 | return ifDesc; 47 | } 48 | 49 | public String getType() { 50 | return type; 51 | } 52 | 53 | public boolean isObs() { 54 | return obs; 55 | } 56 | 57 | public boolean isSubscribed() { 58 | return isSubscribed; 59 | } 60 | 61 | public String getUriPath() { 62 | return uri; 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | return String.format("Resources [uri='%s', rt='%s', ifDesc='%s', type='%s', obs=%s, subscribed=%s]", uri, rt, ifDesc, type, obs, isSubscribed); 68 | } 69 | 70 | public static ResourceMetadata from(ResourceInfo resourceInfo, boolean isSubscribed) { 71 | return new ResourceMetadata(resourceInfo.getPath(), resourceInfo.getRt(), resourceInfo.getInterfaceDescription(), 72 | resourceInfo.getCt(), resourceInfo.isObs(), isSubscribed); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/ResourcePath.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.mbed.example.data; 18 | 19 | /** 20 | * @author szymon 21 | */ 22 | public final class ResourcePath { 23 | private final String endpointName; 24 | private final String path; 25 | 26 | public static ResourcePath of(String endpointName, String path) { 27 | return new ResourcePath(endpointName, path); 28 | } 29 | 30 | public ResourcePath(String endpointName, String path) { 31 | if (endpointName == null || path == null) { 32 | throw new NullPointerException(); 33 | } 34 | this.endpointName = endpointName; 35 | this.path = path; 36 | } 37 | 38 | public String getPath(){ 39 | return path; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) { 45 | return true; 46 | } 47 | if (o == null || getClass() != o.getClass()) { 48 | return false; 49 | } 50 | 51 | ResourcePath that = (ResourcePath) o; 52 | 53 | if (!endpointName.equals(that.endpointName)) { 54 | return false; 55 | } 56 | return path.equals(that.path); 57 | 58 | } 59 | 60 | @Override 61 | public int hashCode() { 62 | int result = endpointName.hashCode(); 63 | result = 31 * result + path.hashCode(); 64 | return result; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return String.format("[endpointName='%s', path='%s']", endpointName, path); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/ResourceValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.data; 19 | 20 | /** 21 | * @author szymon 22 | */ 23 | public final class ResourceValue { 24 | private final String value; 25 | private final long timestamp; 26 | private final boolean isWaitingForResponse; 27 | private final int statusCode; 28 | private final String errorMessage; 29 | private final String contentType; 30 | private final int maxAge; 31 | private final boolean isNotification; 32 | 33 | public ResourceValue(String value, boolean isWaitingForResponse, int statusCode, String errorMessage, String contentType, int maxAge, boolean isNotification) { 34 | this(value, isWaitingForResponse, statusCode, errorMessage, System.currentTimeMillis(), contentType, maxAge, isNotification); 35 | } 36 | 37 | public ResourceValue(String value, boolean isWaitingForResponse, int statusCode, String errorMessage, long timestamp, String contentType, int maxAge, boolean isNotification) { 38 | this.value = value; 39 | this.isWaitingForResponse = isWaitingForResponse; 40 | this.statusCode = statusCode; 41 | this.errorMessage = errorMessage; 42 | this.timestamp = timestamp; 43 | this.contentType = contentType; 44 | this.maxAge = maxAge; 45 | this.isNotification = isNotification; 46 | } 47 | 48 | public String getValue() { 49 | return value; 50 | } 51 | 52 | public int getStatusCode() { 53 | return statusCode; 54 | } 55 | 56 | public String getErrorMessage() { 57 | return errorMessage; 58 | } 59 | 60 | public boolean isWaitingForResponse() { 61 | return isWaitingForResponse; 62 | } 63 | 64 | public long getTimestamp() { 65 | return timestamp; 66 | } 67 | 68 | public int getMaxAge() { 69 | return maxAge; 70 | } 71 | 72 | public String getContentType() { 73 | return contentType; 74 | } 75 | 76 | public boolean isNotification() { 77 | return isNotification; 78 | } 79 | 80 | @Override 81 | public String toString() { 82 | return String.format("ResourceValue [value='%s', isWaitingForResponse=%s, statusCode=%d, errorMessage='%s', contentType='%s', maxAge=%d, timestamp=%d, isNotification=%s]", 83 | value, isWaitingForResponse, statusCode, errorMessage, contentType, maxAge, timestamp, isNotification); 84 | } 85 | 86 | @Override 87 | public boolean equals(Object o) { 88 | if (this == o) { 89 | return true; 90 | } 91 | if (o == null || getClass() != o.getClass()) { 92 | return false; 93 | } 94 | 95 | ResourceValue that = (ResourceValue) o; 96 | 97 | if (isWaitingForResponse != that.isWaitingForResponse) { 98 | return false; 99 | } 100 | if (isNotification != that.isNotification) { 101 | return false; 102 | } 103 | if (statusCode != that.statusCode) { 104 | return false; 105 | } 106 | if (value != null ? !value.equals(that.value) : that.value != null) { 107 | return false; 108 | } 109 | if (maxAge != that.maxAge) { 110 | return false; 111 | } 112 | if (errorMessage != null ? !errorMessage.equals(that.errorMessage) : that.errorMessage != null) { 113 | return false; 114 | } 115 | return !(contentType != null ? !contentType.equals(that.contentType) : that.contentType != null); 116 | } 117 | 118 | @Override 119 | public int hashCode() { 120 | int result = value != null ? value.hashCode() : 0; 121 | result = 31 * result + (isWaitingForResponse ? 1 : 0); 122 | result = 31 * result + (isNotification ? 1 : 0); 123 | result = 31 * result + statusCode; 124 | result = 31 * result + maxAge; 125 | result = 31 * result + (contentType != null ? contentType.hashCode() : 0); 126 | result = 31 * result + (errorMessage != null ? errorMessage.hashCode() : 0); 127 | return result; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/ServerConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.data; 19 | 20 | /** 21 | * @author KALLE 22 | */ 23 | 24 | public class ServerConfiguration { 25 | private String address; 26 | private String username; 27 | private String password; 28 | private String token; 29 | private String pushurl; 30 | 31 | public ServerConfiguration() { 32 | //empty constructor for JSON parsing 33 | } 34 | 35 | 36 | public ServerConfiguration(String address, String username, String password, String token, String pushurl) { 37 | this.address = address; 38 | this.username = username; 39 | this.password = password; 40 | this.token = token; 41 | this.pushurl = pushurl; 42 | } 43 | 44 | public String getAddress() { 45 | return address; 46 | } 47 | 48 | public void setAddress(String address) { 49 | this.address = address; 50 | } 51 | 52 | public String getUsername() { 53 | return username; 54 | } 55 | 56 | public void setUsername(String username) { 57 | this.username = username; 58 | } 59 | 60 | public String getPassword() { 61 | return password; 62 | } 63 | 64 | public void setPassword(String password) { 65 | this.password = password; 66 | } 67 | 68 | public String getToken() { 69 | return token; 70 | } 71 | 72 | public void setToken(String token) { 73 | this.token = token; 74 | } 75 | 76 | public String getPushurl() { 77 | return pushurl; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/tlv/LWM2MID.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.data.tlv; 19 | 20 | import java.util.Objects; 21 | 22 | public class LWM2MID implements Comparable { 23 | 24 | private final String stringId; 25 | private final int intId; 26 | 27 | public static LWM2MID from (int intId) { 28 | return new LWM2MID(intId); 29 | } 30 | 31 | public LWM2MID (int intId) { 32 | this.stringId = String.valueOf(intId); 33 | this.intId = intId; 34 | } 35 | 36 | public int intValue() { 37 | return intId; 38 | } 39 | 40 | @Override 41 | public boolean equals(Object obj) { 42 | if (obj instanceof LWM2MID) { 43 | LWM2MID that = (LWM2MID) obj; 44 | return Objects.equals(this.stringId,that.stringId); 45 | } 46 | return false; 47 | } 48 | 49 | @Override 50 | public int hashCode() { 51 | return Objects.hashCode(intId); 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return stringId; 57 | } 58 | 59 | @Override 60 | public int compareTo(LWM2MID that) { 61 | if (this.stringId == null) { 62 | return that.stringId == null ? 0 : -1; 63 | } else { 64 | return that.stringId == null ? 1 : this.stringId.compareTo(that.stringId); 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/tlv/LWM2MObjectInstance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.mbed.example.data.tlv; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | import org.mbed.example.common.string.Utf8String; 23 | 24 | public class LWM2MObjectInstance { 25 | 26 | private final LWM2MID id; 27 | private final List resources; 28 | 29 | public LWM2MObjectInstance (LWM2MID id, List resources) { 30 | if (id != null) { 31 | this.id = id; 32 | this.resources = new ArrayList<>(resources); 33 | } else { 34 | throw new NullPointerException("LWM2MID"); 35 | } 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return resources.stream() 41 | .map(r -> { 42 | if(r.hasNestedInstances()){ 43 | return r.getNestedInstances().stream() 44 | .map(i -> "\t/" + id + "/" + r.getId() + "/" + i.getId() + "\t\t\t" + Utf8String.from(i.getValue())) 45 | .collect(Collectors.joining("\r\n")); 46 | }else{ 47 | return "\t/" + id + "/" + r.getId() + "\t\t\t" + Utf8String.from(r.getValue()); 48 | } 49 | }) 50 | .collect(Collectors.joining("\r\n")); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/tlv/LWM2MResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.mbed.example.data.tlv; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | import org.mbed.example.common.string.Utf8String; 23 | 24 | public class LWM2MResource extends LWM2MResourceInstance { 25 | 26 | private List instances; 27 | 28 | private LWM2MResource (LWM2MID id) { 29 | super (id); 30 | } 31 | 32 | public LWM2MResource (LWM2MID id, byte[] value) { 33 | super (id, value); 34 | this.validate(); 35 | } 36 | 37 | public LWM2MResource (LWM2MID id, List instances) { 38 | this (id); 39 | this.instances = new ArrayList<>(instances); 40 | this.validate(); 41 | } 42 | 43 | public final boolean hasNestedInstances() { 44 | return instances != null && !instances.isEmpty(); 45 | } 46 | 47 | public List getNestedInstances() { 48 | return instances; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | if(hasNestedInstances()){ 54 | return getNestedInstances().stream() 55 | .map(i -> "\t/" + getId() + "/" + i.getId() + "\t\t\t" + Utf8String.from(i.getValue())) 56 | .collect(Collectors.joining("\r\n")); 57 | }else{ 58 | return "\t/" + getId() + "\t\t\t" + Utf8String.from(getValue()); 59 | } 60 | } 61 | 62 | private void validate() throws IllegalArgumentException { 63 | if (getId().intValue() < 0 || getId().intValue() > 65535) { 64 | throw new IllegalArgumentException("Resource ID must be between 0 and 65535."); 65 | } 66 | if (hasValue() == hasNestedInstances()) { 67 | throw new IllegalArgumentException("Resource must be a value or nested resource instances."); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/tlv/LWM2MResourceInstance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.mbed.example.data.tlv; 18 | 19 | 20 | import org.mbed.example.common.string.HexArray; 21 | 22 | public class LWM2MResourceInstance { 23 | 24 | private final LWM2MID id; 25 | private byte[] value; 26 | 27 | protected LWM2MResourceInstance(LWM2MID id) { 28 | if (id != null) { 29 | this.id = id; 30 | } else { 31 | throw new NullPointerException("LWM2MID"); 32 | } 33 | } 34 | 35 | public LWM2MResourceInstance(LWM2MID id, byte[] value) { 36 | this(id); 37 | this.value = value; 38 | 39 | if (value == null) { 40 | throw new IllegalArgumentException("Missing value from resource instance."); 41 | } 42 | } 43 | 44 | public LWM2MID getId() { 45 | return id; 46 | } 47 | 48 | public byte[] getValue() { 49 | return value; 50 | } 51 | 52 | public boolean hasValue() { 53 | return value != null; 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return "Resource instance [id:" + id + ", value: " + HexArray.toHex(value) + "]"; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/tlv/LWM2MResourceType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.data.tlv; 19 | 20 | public enum LWM2MResourceType { 21 | 22 | STRING, INTEGER, FLOAT, BOOLEAN, OPAQUE, TIME, OBJECTLINK 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/tlv/TLV.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.mbed.example.data.tlv; 18 | 19 | public class TLV { 20 | 21 | /** HTTP Media type for OMA TLV content. */ 22 | public static final String CT_APPLICATION_LWM2M_TLV = "application/vnd.oma.lwm2m+tlv"; 23 | 24 | static final byte TYPE_RESOURCE = (byte) 0b11_000000; 25 | static final byte TYPE_MULTIPLE_RESOURCE = (byte) 0b10_000000; 26 | static final byte TYPE_RESOURCE_INSTANCE = (byte) 0b01_000000; 27 | static final byte TYPE_OBJECT_INSTANCE = (byte) 0b00_000000; 28 | 29 | static final int ID8 = 0b00_000000; 30 | static final int ID16 = 0b00_1_00000; 31 | 32 | static final int LENGTH8 = 0b000_01_000; 33 | static final int LENGTH16 = 0b000_10_000; 34 | static final int LENGTH24 = 0b000_11_000; 35 | 36 | private TLV() { 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/data/tlv/TLVDeserializer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2014 ARM Limited. All rights reserved. 3 | */ 4 | package org.mbed.example.data.tlv; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | 11 | /** 12 | * TLV Deserialiser get the object instances and resources as binary data and 13 | * builds the lwm2m representation from it. See OMA-LWM2M 14 | * specification, chapter 6.1 for the resource model and chapter 6.3.3 for 15 | * the OMA-TLV specification. 16 | */ 17 | public class TLVDeserializer { 18 | 19 | private static class TypeIdLength { 20 | private byte[] tlv; 21 | private int offset; 22 | private int type; 23 | private int id; 24 | private int length; 25 | 26 | private static TypeIdLength createTypeIdLength(byte[] tlv, int offset) { 27 | TypeIdLength til = new TypeIdLength(); 28 | til.tlv = tlv; 29 | til.offset = offset; 30 | til.type = tlv[offset] & (byte) 0b11_000000; 31 | til.id = -1; 32 | til.length = 0; 33 | return til; 34 | } 35 | 36 | private TypeIdLength deserialize() { 37 | try { 38 | int idLength = tlv[offset] & TLV.ID16; 39 | int lengthType = tlv[offset] & TLV.LENGTH24; 40 | if (lengthType == 0) { 41 | length = tlv[offset] & (byte) 0b00000_111; 42 | } 43 | offset++; 44 | 45 | deserialiseID(idLength); 46 | deserialiseLength(lengthType); 47 | } catch (IndexOutOfBoundsException exception) { 48 | throw new IllegalArgumentException("Premature end of content...", exception); 49 | } 50 | 51 | return this; 52 | } 53 | 54 | private void deserialiseID (int idLength) { 55 | id = tlv[offset++] & 0xFF; 56 | if (idLength == TLV.ID16) { 57 | id = (id << 8) + (tlv[offset++] & 0xFF); 58 | } 59 | } 60 | 61 | private void deserialiseLength (int lengthType) { 62 | if (lengthType > 0) { 63 | length = tlv[offset++] & 0xFF; 64 | } 65 | if (lengthType > TLV.LENGTH8) { 66 | length = (length << 8) + (tlv[offset++] & 0xFF); 67 | } 68 | if (lengthType > TLV.LENGTH16) { 69 | length = (length << 8) + (tlv[offset++] & 0xFF); 70 | } 71 | } 72 | 73 | } 74 | 75 | /** 76 | * This method checks whether the given binary encodes an object instance 77 | * or something else. It returns true if bits 7-6 of the first 78 | * byte is "00". 79 | * @param tlv Binary to be checked as LWM2M object instance 80 | * @return true or false. 81 | */ 82 | public static boolean isObjectInstance (byte[] tlv) { 83 | return isObjectInstance(tlv, 0); 84 | } 85 | 86 | /** 87 | * This method checks whether the given binary encodes a resource or 88 | * something else. It returns true if bits 7-6 of the first 89 | * byte is "11". 90 | * @param tlv Binary to be checked as LWM2M resource. 91 | * @return true or false. 92 | */ 93 | public static boolean isResource (byte[] tlv) { 94 | return isResource(tlv, 0); 95 | } 96 | 97 | /** 98 | * This method checks whether the given binary encodes a multiple resource 99 | * or something else. It returns true if bits 7-6 of the first 100 | * byte is "10". 101 | * @param tlv Binary to be checked as LWM2M multiple resource. 102 | * @return true or false. 103 | */ 104 | public static boolean isMultipleResource (byte[] tlv) { 105 | return isMultipleResource(tlv, 0); 106 | } 107 | 108 | /** 109 | * This method checks whether the given binary encodes a resource instance 110 | * or something else. It returns true if bits 7-6 of the first 111 | * byte is "01". 112 | * @param tlv Binary to be checked as LWM2M resource instance. 113 | * @return true or false. 114 | */ 115 | public static boolean isResourceInstance (byte[] tlv) { 116 | return isResourceInstance(tlv, 0); 117 | } 118 | 119 | /** 120 | * Deserialises the given binary that must encode object instances. Binary 121 | * array can be checked before invoking this method with 122 | * {@link #isObjectInstance(byte[])}. 123 | * @param tlv Binary in OMA-TLV format 124 | * @return List of LWM2MObjectInstance objects. 125 | * @throws IllegalArgumentException if given binary is not a valid OMA-TLV 126 | * or it encodes a structure other than object instances. 127 | * @see #deserializeResources(byte[]) 128 | */ 129 | public static List deserialiseObjectInstances (byte[] tlv) { 130 | if (!isObjectInstance(tlv) ) { 131 | throw new IllegalArgumentException("Object instance not found."); 132 | } 133 | 134 | return deserializeObjectInstances (tlv, 0, new ArrayList<>() ); 135 | } 136 | 137 | /** 138 | * Deserialises the given binary that must encode resources. Binary array 139 | * can be checked before invoking this method with {@link #isResource(byte[])}. 140 | * @param tlv Binary in OMA-TLV format 141 | * @return List of LWM2MObjectInstance objects. 142 | * @throws IllegalArgumentException if given binary is not a valid OMA-TLV 143 | * or it encodes a structure other than object instances. 144 | * @see #deserializeResources(byte[]) 145 | */ 146 | public static List deserializeResources (byte[] tlv) { 147 | if (!isResource(tlv) && !isMultipleResource(tlv)) { 148 | throw new IllegalArgumentException("Resource or multiple resource not found."); 149 | } 150 | 151 | return deserializeResources (tlv, 0, new ArrayList<>() ); 152 | } 153 | 154 | private static List deserializeObjectInstances(byte[] tlv, int offset, List list) { 155 | TypeIdLength til = TypeIdLength.createTypeIdLength(tlv, offset).deserialize(); 156 | offset = til.offset; 157 | 158 | if (til.type == TLV.TYPE_OBJECT_INSTANCE) { 159 | List instances = new ArrayList<>(); 160 | byte[] nested = Arrays.copyOfRange(tlv, offset, offset + til.length); 161 | deserializeResources(nested, 0, instances); 162 | list.add (new LWM2MObjectInstance(LWM2MID.from(til.id), instances)); 163 | } else { 164 | throw new IllegalArgumentException("Object instance is expected at index:" + offset); 165 | } 166 | 167 | offset += til.length; 168 | 169 | return offset < tlv.length ? deserializeObjectInstances(tlv, offset, list) : list; 170 | } 171 | 172 | private static List deserializeResources (byte[] tlv, int offset, List list) { 173 | TypeIdLength til = TypeIdLength.createTypeIdLength(tlv, offset).deserialize(); 174 | offset = til.offset; 175 | 176 | if (til.type == TLV.TYPE_RESOURCE || til.type == TLV.TYPE_RESOURCE_INSTANCE) { 177 | byte[] value = til.length > 0 ? Arrays.copyOfRange(tlv, offset, offset + til.length) : new byte[0]; 178 | list.add (new LWM2MResource(LWM2MID.from(til.id), value)); 179 | } else if (til.type == TLV.TYPE_MULTIPLE_RESOURCE) { 180 | List instances = new ArrayList<>(); 181 | byte[] nested = Arrays.copyOfRange(tlv, offset, offset + til.length); 182 | deserializeResourceInstances (nested, 0, instances); 183 | list.add (new LWM2MResource(LWM2MID.from(til.id), instances)); 184 | } else { 185 | throw new IllegalArgumentException("Resource is expected at index:" + offset); 186 | } 187 | 188 | offset += til.length; 189 | 190 | return offset < tlv.length ? deserializeResources(tlv, offset, list) : list; 191 | } 192 | 193 | private static List deserializeResourceInstances (byte[] tlv, int offset, List list) { 194 | TypeIdLength til = TypeIdLength.createTypeIdLength(tlv, offset).deserialize(); 195 | offset = til.offset; 196 | 197 | if (til.type == TLV.TYPE_RESOURCE_INSTANCE) { 198 | byte[] value = til.length > 0 ? Arrays.copyOfRange(tlv, offset, offset + til.length) : new byte[0]; 199 | list.add (new LWM2MResourceInstance(LWM2MID.from(til.id), value)); 200 | } else { 201 | throw new IllegalArgumentException("Resource instance is expected at index:" + offset); 202 | } 203 | 204 | offset += til.length; 205 | 206 | return offset < tlv.length ? deserializeResourceInstances(tlv, offset, list) : list; 207 | } 208 | 209 | private static boolean isObjectInstance (byte[] tlv, int offset) { 210 | return (tlv[offset] & (byte) 0b11_000000) == TLV.TYPE_OBJECT_INSTANCE; 211 | } 212 | 213 | private static boolean isResource (byte[] tlv, int offset) { 214 | return (tlv[offset] & (byte) 0b11_000000) == TLV.TYPE_RESOURCE; 215 | } 216 | 217 | private static boolean isMultipleResource (byte[] tlv, int offset) { 218 | return (tlv[offset] & (byte) 0b11_000000) == TLV.TYPE_MULTIPLE_RESOURCE; 219 | } 220 | 221 | private static boolean isResourceInstance (byte[] tlv, int offset) { 222 | return (tlv[offset] & (byte) 0b11_000000) == TLV.TYPE_RESOURCE_INSTANCE; 223 | } 224 | 225 | } 226 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/resources/ConfigurationResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.resources; 19 | 20 | import java.net.ConnectException; 21 | import javax.inject.Inject; 22 | import javax.inject.Singleton; 23 | import javax.ws.rs.BadRequestException; 24 | import javax.ws.rs.Consumes; 25 | import javax.ws.rs.GET; 26 | import javax.ws.rs.POST; 27 | import javax.ws.rs.Path; 28 | import javax.ws.rs.Produces; 29 | import javax.ws.rs.core.MediaType; 30 | import javax.ws.rs.core.Response; 31 | import javax.ws.rs.core.Response.Status; 32 | import org.mbed.example.MbedClientService; 33 | import org.mbed.example.data.ServerConfiguration; 34 | import org.slf4j.Logger; 35 | import org.slf4j.LoggerFactory; 36 | 37 | /** 38 | * @author KALLE 39 | */ 40 | @Path("/configuration") 41 | @Singleton 42 | public final class ConfigurationResource { 43 | 44 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationResource.class); 45 | private final MbedClientService clientCtr; 46 | private ServerConfiguration serverConfiguration; 47 | 48 | @Inject 49 | public ConfigurationResource(MbedClientService mbedClientService) { 50 | this.clientCtr = mbedClientService; 51 | this.serverConfiguration = MbedClientService.DEFAULT_SERVER_CONFIGURATION; 52 | } 53 | 54 | /** 55 | * Returns Server Configuration 56 | * 57 | * @return server configuration 58 | */ 59 | @GET 60 | @Produces(MediaType.APPLICATION_JSON) 61 | public ServerConfiguration getConfiguration() { 62 | LOGGER.debug("Reading server configuration."); 63 | return serverConfiguration; 64 | } 65 | 66 | /** 67 | * Sets configuration 68 | * 69 | * @param newConf new configuration 70 | */ 71 | @POST 72 | @Consumes(MediaType.APPLICATION_JSON) 73 | public void setConfiguration(ServerConfiguration newConf) { 74 | LOGGER.debug("Writing server configuration."); 75 | this.serverConfiguration = newConf; 76 | try { 77 | String token = newConf.getToken(); 78 | if (token != null && !token.trim().contains(" ")) { 79 | newConf.setToken("bearer " + token.trim()); 80 | } 81 | clientCtr.createConnection(serverConfiguration); 82 | } catch (Exception e) { 83 | String message; 84 | if (e.getCause() instanceof ConnectException) { 85 | message = "Cannot connect to Server"; 86 | } else { 87 | message = e.getMessage(); 88 | } 89 | throw new BadRequestException(Response.status(Status.BAD_REQUEST).entity(message).type(MediaType.TEXT_PLAIN).build(), e); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/resources/EndpointsResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.resources; 19 | 20 | import com.arm.mbed.restclient.endpoint.Entity; 21 | import com.arm.mbed.restclient.endpoint.PreSubscriptionEntry; 22 | import com.arm.mbed.restclient.endpoint.ResponseListener; 23 | import com.arm.mbed.restclient.entity.EndpointResponse; 24 | import com.arm.mbed.restclient.entity.notification.EndpointDescription; 25 | import com.arm.mbed.restclient.entity.notification.ResourceInfo; 26 | import java.util.Arrays; 27 | import java.util.Collections; 28 | import java.util.List; 29 | import java.util.Map; 30 | import java.util.regex.Pattern; 31 | import java.util.stream.Collectors; 32 | import javax.inject.Inject; 33 | import javax.inject.Singleton; 34 | import javax.ws.rs.ClientErrorException; 35 | import javax.ws.rs.Consumes; 36 | import javax.ws.rs.DELETE; 37 | import javax.ws.rs.GET; 38 | import javax.ws.rs.NotFoundException; 39 | import javax.ws.rs.POST; 40 | import javax.ws.rs.PUT; 41 | import javax.ws.rs.Path; 42 | import javax.ws.rs.PathParam; 43 | import javax.ws.rs.Produces; 44 | import javax.ws.rs.core.MediaType; 45 | import org.mbed.example.MbedClientService; 46 | import org.mbed.example.data.EndpointMetadata; 47 | import org.mbed.example.data.ResourceMetadata; 48 | import org.mbed.example.data.ResourcePath; 49 | import org.mbed.example.data.ResourceValue; 50 | import org.slf4j.Logger; 51 | import org.slf4j.LoggerFactory; 52 | 53 | /** 54 | * Created by mitvah01 on 29.6.2015. 55 | */ 56 | @Path("/endpoints") 57 | @Singleton 58 | public final class EndpointsResource { 59 | private static final Logger LOGGER = LoggerFactory.getLogger(EndpointsResource.class); 60 | private final MbedClientService clientCtr; 61 | private final static String RESOURCEPATH = "resource-path"; 62 | private final static String ENDPOINTNAME = "endpoint-name"; 63 | 64 | @Inject 65 | public EndpointsResource(MbedClientService mbedClientService) { 66 | this.clientCtr = mbedClientService; 67 | } 68 | 69 | /** 70 | * Returns endpoints in Json format 71 | */ 72 | @GET 73 | @Produces(MediaType.APPLICATION_JSON) 74 | public List getEndpoints() { 75 | //return only list with endpoint name and type 76 | return clientCtr.endpointContainer().getAllEndpoints().stream().map(EndpointMetadata::from).collect(Collectors.toList()); 77 | } 78 | 79 | /** 80 | * Returns endpoints resources in Json format 81 | * 82 | * @param name String name of the endpoint 83 | */ 84 | @GET 85 | @Path("{endpoint-name}") 86 | @Produces(MediaType.APPLICATION_JSON) 87 | public List getEndpointResources(@PathParam(ENDPOINTNAME) String name) { 88 | EndpointDescription endpoint = clientCtr.endpointContainer().getEndpoint(name); 89 | if (endpoint == null) { 90 | //endpoint does not exists 91 | throw new NotFoundException(); 92 | } 93 | 94 | ResourceInfo[] resourceList = endpoint.getResources(); 95 | if (resourceList == null) { 96 | //resource list is missing, try to reload it 97 | resourceList = clientCtr.endpointContainer().updateResourceList(name, clientCtr.client().endpoint(name).readResourceList()); 98 | if (resourceList == null) { 99 | //still missing 100 | return Collections.emptyList(); 101 | } 102 | } 103 | List preSubscriptionEntryList = clientCtr.client().preSubscriptions().read(); 104 | return Arrays.stream(resourceList).map(r -> ResourceMetadata.from(r, isSubscribed(preSubscriptionEntryList, r, name, endpoint.getType()))).collect(Collectors.toList()); 105 | } 106 | 107 | private boolean isSubscribed(List preSubscriptionEntryList,ResourceInfo resourceInfo, String endpointName, String type) { 108 | if (resourceInfo.isObs()) { 109 | for (PreSubscriptionEntry preSubscriptionEntry : preSubscriptionEntryList) { 110 | if (isSubscribed(resourceInfo, endpointName, type, preSubscriptionEntry)) { 111 | return true; 112 | } 113 | } 114 | } 115 | return false; 116 | } 117 | 118 | private static boolean isSubscribed(ResourceInfo resourceInfo, String endpointName, String type, PreSubscriptionEntry preSubscriptionEntry) { 119 | if ((preSubscriptionEntry.getEndpointType() == null || type != null && Pattern.matches(preSubscriptionEntry.getEndpointType().replace("*", ".*"), type)) && 120 | (preSubscriptionEntry.getEndpointName() == null || Pattern.matches(preSubscriptionEntry.getEndpointName().replace("*", ".*"), endpointName))) { 121 | if (preSubscriptionEntry.getUriPathPatterns() == null) { 122 | return true; 123 | } else { 124 | for (String path : preSubscriptionEntry.getUriPathPatterns().get(0).split(",")) { 125 | if (Pattern.matches(path.replace("*", ".*"), resourceInfo.getPath())) { 126 | return true; 127 | } 128 | } 129 | } 130 | } 131 | return false; 132 | } 133 | 134 | @GET 135 | @Path("/{endpoint-name}/request/{resource-path : .+}") 136 | public void invokeProxyRequest(@PathParam(ENDPOINTNAME) String name, @PathParam(RESOURCEPATH) String path) throws ClientErrorException { 137 | //initiate request 138 | final ResourcePath resourcePath = checkConcurrency(name, path); 139 | LOGGER.debug("Making request GET {}", resourcePath); 140 | clientCtr.client().endpoint(name).resource(resourcePath.getPath()).get(new EndpointResponseListener(resourcePath, null)); 141 | } 142 | 143 | @GET 144 | @Path("/{endpoint-name}/values") 145 | @Produces(MediaType.APPLICATION_JSON) 146 | public Map getResourceValues(@PathParam(ENDPOINTNAME) String endpointName) { 147 | return clientCtr.endpointContainer().getEndpointResourceValues(endpointName); 148 | } 149 | 150 | @PUT 151 | @Path("{endpoint-name}/{resource-path: .+}") 152 | @Consumes(MediaType.TEXT_PLAIN) 153 | public void putResourcesValue(String value, @PathParam(ENDPOINTNAME) String name 154 | , @PathParam(RESOURCEPATH) String path) throws ClientErrorException { 155 | //initiate request 156 | final ResourcePath resourcePath = checkConcurrency(name, path); 157 | LOGGER.debug("Making request PUT {}", resourcePath); 158 | clientCtr.client().endpoint(name).resource(resourcePath.getPath()).put(Entity.text(value), new EndpointResponseListener(resourcePath, value)); 159 | } 160 | 161 | @DELETE 162 | @Path("{endpoint-name}/{resource-path: .+}") 163 | public void deleteResourcesValue(@PathParam(ENDPOINTNAME) String name 164 | , @PathParam(RESOURCEPATH) String path) throws ClientErrorException { 165 | //initiate request 166 | final ResourcePath resourcePath = checkConcurrency(name, path); 167 | LOGGER.debug("Making request DELETE {}", resourcePath); 168 | clientCtr.client().endpoint(name).resource(resourcePath.getPath()).delete(new EndpointResponseListener(resourcePath, null)); 169 | } 170 | 171 | @POST 172 | @Path("{endpoint-name}/{resource-path: .+}") 173 | @Consumes(MediaType.TEXT_PLAIN) 174 | public void postResourcesValue(String value, @PathParam(ENDPOINTNAME) String name 175 | , @PathParam(RESOURCEPATH) String path) throws ClientErrorException { 176 | //initiate request 177 | final ResourcePath resourcePath = checkConcurrency(name, path); 178 | LOGGER.debug("Making request POST {}", resourcePath); 179 | clientCtr.client().endpoint(name).resource(resourcePath.getPath()).post(Entity.text(value), new EndpointResponseListener(resourcePath, value)); 180 | } 181 | 182 | private ResourcePath checkConcurrency(String name, String path) { 183 | path = path.replace("%2F", "/"); 184 | if (path.charAt(0) != '/') { 185 | path = "/" + path; 186 | } 187 | final ResourcePath resourcePath = new ResourcePath(name, path); 188 | if (!clientCtr.endpointContainer().updateResource(resourcePath, true)) { 189 | throw new ClientErrorException("Only one request at a time allowed.", 409); 190 | } 191 | return resourcePath; 192 | } 193 | 194 | private class EndpointResponseListener implements ResponseListener { 195 | private final ResourcePath resourcePath; 196 | private final String value; 197 | 198 | public EndpointResponseListener(ResourcePath resourcePath, String requestedPayload) { 199 | this.resourcePath = resourcePath; 200 | this.value = requestedPayload; 201 | } 202 | 203 | @Override 204 | public void onResponse(EndpointResponse response) { 205 | LOGGER.trace("Response for {} with status: {}", resourcePath, response.getStatus()); 206 | clientCtr.endpointContainer().updateResource(resourcePath, response, value); 207 | } 208 | 209 | @Override 210 | public void onError(Exception ex) { 211 | LOGGER.trace("Response - error: " + ex.getMessage()); 212 | clientCtr.endpointContainer().updateResource(resourcePath, ex.getMessage()); 213 | } 214 | 215 | @Override 216 | public void onAsyncIdResponse() { 217 | //ignore 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/resources/MbedClientResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.resources; 19 | 20 | import javax.inject.Inject; 21 | import javax.ws.rs.GET; 22 | import javax.ws.rs.Path; 23 | import javax.ws.rs.Produces; 24 | import javax.ws.rs.core.MediaType; 25 | import org.mbed.example.MbedClientService; 26 | 27 | /** 28 | * Created by mitvah01 on 3.8.2015. 29 | */ 30 | @Path("/mbedclient") 31 | public class MbedClientResource { 32 | private final MbedClientService clientCtr; 33 | 34 | @Inject 35 | public MbedClientResource(MbedClientService mbedClientService) { 36 | this.clientCtr = mbedClientService; 37 | } 38 | 39 | @GET 40 | @Produces(MediaType.APPLICATION_JSON) 41 | public boolean isConnected() { 42 | return clientCtr.isConnected(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/resources/SubscriptionResources.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.resources; 19 | 20 | import com.arm.mbed.restclient.endpoint.PreSubscriptionEntry; 21 | import com.arm.mbed.restclient.endpoint.PreSubscriptions; 22 | import java.net.ConnectException; 23 | import java.util.List; 24 | import javax.inject.Inject; 25 | import javax.inject.Singleton; 26 | import javax.ws.rs.BadRequestException; 27 | import javax.ws.rs.Consumes; 28 | import javax.ws.rs.GET; 29 | import javax.ws.rs.PUT; 30 | import javax.ws.rs.Path; 31 | import javax.ws.rs.Produces; 32 | import javax.ws.rs.core.MediaType; 33 | import javax.ws.rs.core.Response; 34 | import org.mbed.example.MbedClientService; 35 | import org.slf4j.Logger; 36 | import org.slf4j.LoggerFactory; 37 | 38 | /** 39 | * Created by mitvah01 on 30.6.2015. 40 | */ 41 | @Path("/subscriptions") 42 | @Singleton 43 | public class SubscriptionResources { 44 | private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationResource.class); 45 | private final MbedClientService clientCtr; 46 | 47 | @Inject 48 | SubscriptionResources(MbedClientService mbedClientService) { 49 | this.clientCtr = mbedClientService; 50 | } 51 | 52 | @GET 53 | @Produces(MediaType.APPLICATION_JSON) 54 | public List getSubscriptions() { 55 | try { 56 | return clientCtr.client().preSubscriptions().read(); 57 | } catch (Exception e) { 58 | String message; 59 | if (e.getCause() instanceof ConnectException) { 60 | message = "Cannot connect to Server"; 61 | } else { 62 | message = e.getMessage(); 63 | } 64 | throw new BadRequestException(Response.status(Response.Status.BAD_REQUEST).entity(message).type(MediaType.TEXT_PLAIN).build(), e); 65 | } 66 | } 67 | 68 | @PUT 69 | @Produces(MediaType.APPLICATION_JSON) 70 | @Consumes(MediaType.APPLICATION_JSON) 71 | public void putSubscription(List preSubscriptionEntryList) { 72 | LOGGER.debug("Creating pre subscriptions."); 73 | PreSubscriptions.PreSubscriptionsBuilder preSubscriptionsBuilder; 74 | try { 75 | preSubscriptionsBuilder = clientCtr.client().preSubscriptions().builder(); 76 | } catch (Exception e) { 77 | String message; 78 | if (e.getCause() instanceof ConnectException) { 79 | message = "Cannot connect to Server"; 80 | } else { 81 | message = e.getMessage(); 82 | } 83 | throw new BadRequestException(Response.status(Response.Status.BAD_REQUEST).entity(message).type(MediaType.TEXT_PLAIN).build(), e); 84 | } 85 | if (!preSubscriptionEntryList.isEmpty()) { 86 | for (PreSubscriptionEntry preSubscriptionEntry : preSubscriptionEntryList) { 87 | preSubscriptionsBuilder.endpointName(preSubscriptionEntry.getEndpointName()). 88 | endpointType(preSubscriptionEntry.getEndpointType()); 89 | if (preSubscriptionEntry.getUriPathPatterns() != null) { 90 | preSubscriptionsBuilder.path(preSubscriptionEntry.getUriPathPatterns().get(0)); 91 | } 92 | preSubscriptionsBuilder.newEntry(); 93 | } 94 | } 95 | preSubscriptionsBuilder.create(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/org/mbed/example/resources/WebApiService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.mbed.example.resources; 19 | 20 | import javax.ws.rs.ApplicationPath; 21 | import org.glassfish.jersey.server.ResourceConfig; 22 | 23 | /** 24 | * @author szymon 25 | */ 26 | @ApplicationPath("webapi") 27 | public class WebApiService extends ResourceConfig { 28 | 29 | public WebApiService() { 30 | packages("org.mbed.example"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | # not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | log4j.rootLogger=ALL, CONSOLE 19 | log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 20 | log4j.appender.CONSOLE.Threshold=ALL 21 | log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout 22 | #log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p | %16t | %32C{1}:%4L | %m%n 23 | log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss} %-5p %m%n -------------------------------------------------------------------------------- /src/main/webapp/Devices.html: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ARM 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 | 37 | 77 |
78 | 79 |
80 |

Devices

81 | 82 |
83 | 84 | 85 | 88 | 89 |
90 | 91 |
92 |
93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 103 | 105 | 106 | 107 | 108 | There are no matching 109 | devices. 110 | There are no devices. 111 |
NameType
{{x.name }}{{ x.type }}
112 |
113 |
114 | 115 |
116 | 117 |
118 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 |
129 | 130 | 131 | -------------------------------------------------------------------------------- /src/main/webapp/Resources.html: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ARM 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 42 | 43 | 44 |
45 | 46 | 86 |
87 | 88 |
89 |

90 | 91 |
92 |
93 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 127 | 133 | 144 | 145 | 146 |
PathValueObservable
109 | 117 | 118 | 124 | 125 | 126 | 129 | 132 | 134 | 135 | 138 | 142 | 143 |
147 |
148 | 149 |
150 |
151 |
152 | 153 |
154 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | Devices.html 24 | 25 | -------------------------------------------------------------------------------- /src/main/webapp/css/Custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { 18 | display: none !important; 19 | } 20 | body { 21 | padding-top: 90px; 22 | } 23 | .navbar-custom { 24 | color: #000000; 25 | background-color: #1B2530; 26 | } 27 | .navbar #nav > .active > a { 28 | color: #218FD1; 29 | } 30 | .myLogo { padding: 5px; } 31 | 32 | .form-horizontal .control-label{ 33 | text-align:left !important; 34 | } 35 | .btn-custom { 36 | width: 90px; 37 | line-height: 20px; 38 | box-sizing: border-box; 39 | text-align: center; 40 | border: 0 none; 41 | font-weight: 500; 42 | letter-spacing: 1px; 43 | text-transform: uppercase; 44 | 45 | } 46 | 47 | .fixedSize-130 { 48 | width: 130px; 49 | } 50 | .td_center { 51 | text-align: center; 52 | } 53 | .differentTable{ 54 | border-color: black; 55 | } 56 | .btn-small { 57 | width: 50px; 58 | line-height: 20px; 59 | text-align: center; 60 | //text-transform: uppercase; 61 | } 62 | .div_float { 63 | background-color: #d9edf7; 64 | border-color: #5bc0de; 65 | border-style: solid; 66 | border-width: 2px; 67 | width: 8%; 68 | height: 40%; 69 | line-height: 50px; 70 | position: absolute; 71 | top: 30%; 72 | left: 90%; 73 | right: 2%; 74 | } 75 | 76 | .gray-light { 77 | color: #c0c0c0; 78 | } 79 | .success { 80 | color:#5cb85c; 81 | } 82 | .danger { 83 | color:#d9534f; 84 | } 85 | .warning { 86 | color:#f0ad4e; 87 | } 88 | .primary { 89 | color:#337ab7; 90 | } 91 | .infoColor { 92 | color:#5bc0de; 93 | } 94 | /* Popover Header*/ 95 | .popover-title { 96 | background-color: #5bc0de; 97 | color: #FFFFFF; 98 | font-size: 15px; 99 | text-align:center; 100 | } 101 | .success_popover { 102 | border: 2px solid #5cb85c; 103 | } 104 | .error_popover { 105 | border: 2px solid #d9534f; 106 | } 107 | 108 | /* Popover Header*/ 109 | .success_popover-title { 110 | background-color: #5cb85c; 111 | color: #FFFFFF; 112 | font-size: 15px; 113 | text-align:center; 114 | } 115 | .error_popover-title { 116 | background-color: #d9534f; 117 | color: #FFFFFF; 118 | font-size: 15px; 119 | text-align:center; 120 | } 121 | 122 | /* Popover Body */ 123 | .success_popover-content { 124 | background-color: #FFFFFF; 125 | color: #5cb85c; 126 | padding: 25px; 127 | } 128 | .error_popover-content { 129 | background-color: #FFFFFF; 130 | color: #d9534f; 131 | padding: 25px; 132 | } 133 | 134 | /* Popover Arrow */ 135 | .success_popover-arrow { 136 | border-top-color: #5cb85c !important; 137 | } 138 | .error_popover-arrow { 139 | border-top-color: #d9534f !important; 140 | } 141 | .editable-click 142 | { 143 | border:0.5px solid #cccccc !important; 144 | } 145 | .highlight { 146 | background-color: #b2c5d6 !important; 147 | color: #FFFFFF; 148 | } 149 | .highlight:link{ 150 | color:#FFFFFF !important; 151 | } 152 | 153 | body { background: url("../img/bg.jpg") no-repeat center center fixed !important; 154 | /* http://motivamemes.com/t/imagenes/17130172/Wallpapers-Minimalistas/*/ 155 | -webkit-background-size: cover; 156 | -moz-background-size: cover; 157 | background-size: cover; 158 | -o-background-size: cover;} 159 | 160 | .animate-hide { 161 | -webkit-transition: all linear 0.2s; 162 | transition: all linear 0.2s; 163 | line-height: 35px; 164 | opacity: 1; 165 | } 166 | 167 | .animate-hide.ng-hide { 168 | line-height: 0px; 169 | opacity: 0; 170 | } 171 | 172 | .ng-hide.only-hide { 173 | 174 | visibility: hidden !important; 175 | display: block !important; 176 | } 177 | 178 | .spin { 179 | -webkit-animation: spin .5s infinite linear; 180 | -moz-animation: spin .5s infinite linear; 181 | -o-animation: spin .5s infinite linear; 182 | animation: spin .5s infinite linear; 183 | -webkit-transform-origin: 50% 58%; 184 | transform-origin: 50% 58%; 185 | -ms-transform-origin: 50% 58%; /* IE 9 */ 186 | } 187 | 188 | @-moz-keyframes spin { 189 | from { 190 | -moz-transform: rotate(0deg); 191 | } 192 | to { 193 | -moz-transform: rotate(360deg); 194 | } 195 | } 196 | 197 | @-webkit-keyframes spin { 198 | from { 199 | -webkit-transform: rotate(0deg); 200 | } 201 | to { 202 | -webkit-transform: rotate(360deg); 203 | } 204 | } 205 | 206 | @keyframes spin { 207 | from { 208 | transform: rotate(0deg); 209 | } 210 | to { 211 | transform: rotate(360deg); 212 | } 213 | } 214 | 215 | .vcenter { 216 | display: inline-block; 217 | vertical-align: middle; 218 | float: none; 219 | } -------------------------------------------------------------------------------- /src/main/webapp/img/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/mbed-webapp-example/4666498cb093a517ed72e9562b66f0df218db422/src/main/webapp/img/bg.jpg -------------------------------------------------------------------------------- /src/main/webapp/img/connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/mbed-webapp-example/4666498cb093a517ed72e9562b66f0df218db422/src/main/webapp/img/connected.png -------------------------------------------------------------------------------- /src/main/webapp/img/disconnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/mbed-webapp-example/4666498cb093a517ed72e9562b66f0df218db422/src/main/webapp/img/disconnected.png -------------------------------------------------------------------------------- /src/main/webapp/img/mbed-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ARMmbed/mbed-webapp-example/4666498cb093a517ed72e9562b66f0df218db422/src/main/webapp/img/mbed-logo.png -------------------------------------------------------------------------------- /src/main/webapp/js/app/configurationModule/ConfigurationController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | angular.module('App.controllers', ['ngAnimate']); 19 | angular.module('App.controllers').controller('ConfCtrl', 20 | function ConfCtrl($scope, $http, Configuration, ConnectionStatus, $rootScope) { 21 | $scope.$on("connection", function (event, args) { 22 | $scope.isConnected = args.connected; 23 | $scope.isDisconnected = !args.connected; 24 | }); 25 | ConnectionStatus.getStatus().then( 26 | function (data) { 27 | $scope.isConnected = data.data == true; 28 | $scope.isDisconnected = data.data == false; 29 | }, function (data, status) { 30 | console.log('Error!!', status, data); 31 | }); 32 | Configuration.get().$promise.then(function (data) { 33 | $scope.address = data.address; 34 | $scope.selection = data.token == null ? "userPass" : "token"; 35 | $scope.notifselection = data.pushurl == null ? "pull" : "push"; 36 | $scope.data = data; 37 | }, function (data, status) { 38 | console.log('Error!!', status, data); 39 | }); 40 | $scope.save = function () { 41 | $scope.error = null; 42 | $scope.ok = null; 43 | $scope.done = false; 44 | if ($scope.selection.valueOf() == "userPass") { 45 | $scope.data.token = null; 46 | } 47 | else { 48 | $scope.data.username = null; 49 | $scope.data.password = null; 50 | } 51 | 52 | if ($scope.notifselection.valueOf() == "pull") { 53 | $scope.data.pushurl = null; 54 | } 55 | 56 | Configuration.set({}, $scope.data).$promise.then(function () { 57 | $scope.ok = "Success!"; 58 | $rootScope.$broadcast("connection", {connected: true}); 59 | }, function (data) { 60 | $scope.error = data.data; 61 | $rootScope.$broadcast("connection", {connected: false}); 62 | }).finally(function () { 63 | $scope.done = true; 64 | }); 65 | }; 66 | }); 67 | 68 | angular.module('App.controllers').controller('Ctrl', 69 | function Ctrl($scope, $http, $location, $rootScope, Subscriptions) { 70 | $scope.selection = "userPass"; 71 | $rootScope.$on('$locationChangeStart', function (event) { 72 | if (!tabClicked && $rootScope.notSaved && !confirm("You have unsaved changes, do you want to continue?")) { 73 | event.preventDefault(); 74 | } 75 | else { 76 | $(parent).tab('show'); 77 | } 78 | }); 79 | window.onbeforeunload = function () { 80 | if ($rootScope.notSaved) { 81 | return "You have unsaved changes, do you want to continue?"; 82 | } 83 | }; 84 | var parent; 85 | var tabClicked; 86 | $scope.tabclick = function (event, name) { 87 | parent = event.target; 88 | tabClicked = true; 89 | if (name != 'subscription' && $rootScope.notSaved && !confirm("You have unsaved changes, do you want to continue?")) { 90 | event.preventDefault(); 91 | } 92 | else { 93 | $(parent).tab('show'); 94 | } 95 | }; 96 | $scope.refresh_sub = function () { 97 | $rootScope.subscriptions = Subscriptions.query(); 98 | $rootScope.sub_ok = null; 99 | $rootScope.sub_error = null; 100 | } 101 | }); 102 | angular.module('App.controllers').controller('subCtrl', function ($scope, $filter, Subscriptions, $rootScope) { 103 | $rootScope.notSaved = false; 104 | $scope.show_close = true; 105 | $rootScope.subscriptions = Subscriptions.query(); 106 | $scope.btn_text = 'add'; 107 | 108 | $scope.addRow = function () { 109 | var pre_subscription = {}; 110 | pre_subscription['endpointName'] = ($scope.txt_name == undefined || $scope.txt_name == '') ? null : $scope.txt_name; 111 | pre_subscription['endpointType'] = ($scope.txt_type == undefined || $scope.txt_type == '') ? null : $scope.txt_type; 112 | pre_subscription['uriPathPatterns'] = ($scope.txt_path == undefined || $scope.txt_path == '') ? null : [$scope.txt_path]; 113 | if (pre_subscription['endpointName'] != null || pre_subscription['endpointType'] != null || pre_subscription['uriPathPatterns'] != null) { 114 | if (update_index != -1) { 115 | $scope.subscriptions.splice(update_index, 1); 116 | } 117 | $scope.subscriptions.push(pre_subscription); 118 | $rootScope.notSaved = true; 119 | $scope.ok = null; 120 | $scope.error = null; 121 | $scope.refresh(); 122 | } 123 | }; 124 | var update_index = -1; 125 | $scope.update = function (endpointName, endpointType, uriPathPatterns, row_number) { 126 | $scope.refresh(); 127 | $scope.txt_name = endpointName; 128 | $scope.txt_type = endpointType; 129 | $scope.txt_path = uriPathPatterns; 130 | 131 | update_index = row_number; 132 | $scope.show_close = false; 133 | $scope.btn_text = 'Update'; 134 | }; 135 | $scope.refresh = function () { 136 | $scope.txt_name = ''; 137 | $scope.txt_type = ''; 138 | $scope.txt_path = ''; 139 | update_index = -1; 140 | $scope.show_close = true; 141 | $scope.btn_text = 'Add'; 142 | }; 143 | $scope.delete = function (row_number) { 144 | $scope.subscriptions.splice(row_number, 1); 145 | $scope.refresh(); 146 | $rootScope.notSaved = true; 147 | $scope.ok = null; 148 | $scope.error = null; 149 | }; 150 | $scope.save = function () { 151 | $scope.successfulPush = false; 152 | $rootScope.sub_ok = null; 153 | $rootScope.sub_error = null; 154 | var preSubscriptionList = []; 155 | $filter('filter')($scope.subscriptions, function (d) { 156 | var item = { 157 | "endpointName": d.endpointName, 158 | "endpointType": d.endpointType, 159 | "uriPathPatterns": d.uriPathPatterns 160 | }; 161 | preSubscriptionList.push(item); 162 | }); 163 | Subscriptions.update({}, preSubscriptionList).$promise.then(function () { 164 | $rootScope.sub_ok = "Saved successfully!"; 165 | }, function (data) { 166 | console.log("error in pushing pre-subscription ", data.status, data.statusText); 167 | $rootScope.sub_error = data.statusText; 168 | }).finally(function () { 169 | $scope.successfulPush = true; 170 | }); 171 | $scope.refresh(); 172 | $rootScope.notSaved = false; 173 | }; 174 | }); -------------------------------------------------------------------------------- /src/main/webapp/js/app/configurationModule/ConfigurationDirective.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | angular.module('App.directives', []); 18 | angular.module('App.directives').directive('strongSecret', function () { 19 | return { 20 | restrict: 'A', 21 | link: function (scope, element, attr, ctrl) { 22 | scope.$watch(attr.ngModel, function (v, p, scope) { 23 | if (v != null && v.length != 0) { 24 | if (v.lastIndexOf('/', 0) === 0) { 25 | scope.valid = true; 26 | scope.message = null; 27 | } 28 | else { 29 | scope.valid = false; 30 | scope.message = 'The resource path should start with "/"'; 31 | } 32 | } 33 | else { 34 | scope.valid = null; 35 | scope.message = null; 36 | } 37 | }); 38 | } 39 | }; 40 | }); -------------------------------------------------------------------------------- /src/main/webapp/js/app/configurationModule/ConfigurationService.js: -------------------------------------------------------------------------------- 1 | angular.module('App.services', ['ngResource']); 2 | 3 | angular.module('App.services').factory('Subscriptions', function ($resource) { 4 | return $resource('webapi/subscriptions', {}, { 5 | update: { 6 | method: 'PUT' 7 | } 8 | }); 9 | }); 10 | angular.module('App.services').factory('Configuration', function ($resource) { 11 | return $resource('webapi/configuration', {}, { 12 | set: { 13 | method: 'POST' 14 | }, 15 | get: { 16 | method: 'GET', isArray: false 17 | } 18 | }); 19 | }); 20 | angular.module('App.services').factory('ConnectionStatus', function ($http) { 21 | return { 22 | getStatus: function () { 23 | return $http.get('webapi/mbedclient'); 24 | } 25 | }; 26 | }); -------------------------------------------------------------------------------- /src/main/webapp/js/app/configurationModule/app.js: -------------------------------------------------------------------------------- 1 | angular.module('App', 2 | ['App.services', 3 | 'App.controllers', 4 | 'App.directives']); -------------------------------------------------------------------------------- /src/main/webapp/js/app/deviceModule/DevicesController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | angular.module('App.controllers',[]); 18 | angular.module('App.controllers').controller('Ctrl', function ($scope, Endpoints, ConnectionStatus, Configuration, $window,$location) { 19 | 20 | Endpoints.query().$promise.then(function (data) { 21 | $scope.noDevice = data.length == 0 ? true : false; 22 | $scope.endpoints = data; 23 | }, function (data, status) { 24 | console.log('Error!!', status, data); 25 | }); 26 | ConnectionStatus.getStatus().then( 27 | function (data) { 28 | $scope.isConnected = data.data == true; 29 | $scope.isDisconnected = data.data == false; 30 | console.log('data', data); 31 | }, function (data, status) { 32 | console.log('Error!!', status, data); 33 | }); 34 | Configuration.getConfiguration().then( 35 | function (data) { 36 | $scope.address = data.data.address; 37 | }, function (data, status) { 38 | console.log('Error!!', status, data); 39 | }); 40 | $scope.show_resources = function (name) { 41 | $window.open('Resources.html#/?endpoint=' + name, "_self"); 42 | }; 43 | }); 44 | angular.module('App.controllers').filter('search', function () { 45 | return function (items, str) { 46 | if (str == '') return items; 47 | 48 | var filtered = []; 49 | var rgx = new RegExp(str, ''); 50 | var rgxstart = new RegExp(': ?"' + str); 51 | 52 | angular.forEach(items, function (item) { 53 | var stringified = JSON.stringify(item); 54 | item.points = (stringified.match(rgx) || []).length; 55 | 56 | if (rgxstart.test(stringified)) item.points++; 57 | 58 | if (item.points > 0) filtered.push(item); 59 | }); 60 | return filtered; 61 | } 62 | }); -------------------------------------------------------------------------------- /src/main/webapp/js/app/deviceModule/DevicesService.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | angular.module('App.services', ['ngResource']); 19 | angular.module('App.services').factory('Endpoints', function ($resource) { 20 | return $resource('webapi/endpoints/:endpoint_name/:url_path', { 21 | endpoint_name: '@endpoint_name', 22 | url_path: '@url_path' 23 | }); 24 | }); 25 | angular.module('App.services').factory('Configuration', function ($http) { 26 | return { 27 | getConfiguration: function () { 28 | return $http.get('webapi/configuration'); 29 | } 30 | }; 31 | }); 32 | angular.module('App.services').factory('ConnectionStatus', function ($http) { 33 | return { 34 | getStatus: function () { 35 | return $http.get('webapi/mbedclient'); 36 | } 37 | }; 38 | }); 39 | -------------------------------------------------------------------------------- /src/main/webapp/js/app/deviceModule/app.js: -------------------------------------------------------------------------------- 1 | angular.module('App', 2 | ['App.services', 3 | 'App.controllers']); -------------------------------------------------------------------------------- /src/main/webapp/js/app/resourceModule/ResourcesController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | angular.module('App.controllers', ['angularMoment']); 19 | angular.module('App.controllers').controller('Ctrl', function ($scope, Request, Endpoints, GetValues, ConnectionStatus 20 | , Configuration, $compile, $interval, $filter, $location) { 21 | 22 | //modify buttons style 23 | var dynamical_buttons = $compile('
' + 24 | '' + 25 | '
' + 26 | '
')($scope); 27 | $.fn.editableform.buttons = dynamical_buttons; 28 | $scope.isHidden = true; 29 | $scope.isLoading = false; 30 | $scope.isConnected = false; 31 | $scope.isDisonnected = false; 32 | 33 | ConnectionStatus.getStatus().then( 34 | function (data) { 35 | $scope.isConnected = data.data == true; 36 | $scope.isDisconnected = data.data == false; 37 | console.log('data', data); 38 | }, function (data, status) { 39 | console.log('Error!!', status, data); 40 | }); 41 | Configuration.getConfiguration().then( 42 | function (data) { 43 | $scope.address = data.data.address; 44 | }, function (data, status) { 45 | console.log('Error!!', status, data); 46 | }); 47 | var endpoint_name = $location.search().endpoint; 48 | $scope.detail = endpoint_name; 49 | $scope.endresources = Endpoints.query({'endpoint_name': endpoint_name}) 50 | .$promise.then(function (value) { 51 | $scope.endresources = value; 52 | console.log($scope.endresources); 53 | }, function (data, status) { 54 | console.error('Error!!', status, data); 55 | }); 56 | var waiting_endpoint; 57 | var waiting_uri; 58 | $scope.get = function (event, name, path, selected_record) { 59 | $(parent).editable('toggle'); 60 | Request.sendRequest(name, path).then(function (data) { 61 | selected_record.show = true; 62 | $scope.isDisabled = "true"; 63 | waiting_endpoint = name; 64 | waiting_uri = path; 65 | }, function (data, status) { 66 | console.error('Error!!', status, data); 67 | selected_record.show = false; 68 | }); 69 | }; 70 | $scope.put = function (event, name) { 71 | var value = $('#commandValue')[0].value; 72 | $(parent).editable('toggle'); 73 | Endpoints.update({endpoint_name: name, url_path: path}, value).$promise.then(function () { 74 | selected_record.show = true; 75 | }, function (data, status) { 76 | console.error('Error!!', status, data); 77 | selected_record.show = false; 78 | }); 79 | }; 80 | $scope.post = function (event, name) { 81 | var value = $('#commandValue')[0].value; 82 | $(parent).editable('toggle'); 83 | Endpoints.set({endpoint_name: name, url_path: path}, value).$promise.then(function () { 84 | selected_record.show = true; 85 | }, function (data, status) { 86 | console.error('Error!!', status, data); 87 | selected_record.show = false; 88 | }); 89 | }; 90 | $scope.delete = function (event, name) { 91 | $(parent).editable('toggle'); 92 | Endpoints.remove({endpoint_name: name, url_path: path}).$promise.then(function () { 93 | selected_record.show = true; 94 | }, function (data, status) { 95 | console.error('Error!!', status, data); 96 | selected_record.show = false; 97 | }); 98 | }; 99 | var parent; 100 | var path; 101 | var selected_record; 102 | /*The popup does not have access to path and selected row so we need to keep them in vars.*/ 103 | $scope.action_clicked = function (event, selected_path, record) { 104 | parent = event.target; 105 | path = selected_path.replace(/\//g, '%2F'); 106 | selected_record = record; 107 | }; 108 | setInterval(function () { 109 | if (endpoint_name != "none") { 110 | GetValues.getValues(endpoint_name).then( 111 | function (results) { 112 | angular.forEach(results, function (value, key) { 113 | var single_object = $filter('filter')($scope.endresources, function (d) { 114 | var splited_data = key.toString().split("'"); 115 | var endpoint = splited_data[1]; 116 | var path = splited_data[3]; 117 | if (endpoint_name == endpoint && d.uriPath == path && !value.waitingForResponse) { 118 | if (value.statusCode == 200) { 119 | d.val = value.value; 120 | d.lastUpdate = value.timestamp; 121 | d.content = "
Content Type: " + value.contentType 122 | + "
maxAge: " + value.maxAge; 123 | d.success = true; 124 | } 125 | else { 126 | d.val = "Error"; 127 | d.lastUpdate = "Error number " + value.statusCode + ": " + (value.errorMessage == null ? "" : value.errorMessage); 128 | d.success = false; 129 | } 130 | d.show = false; 131 | d.notification = value.notification; 132 | if (waiting_endpoint == endpoint && waiting_uri == path) { 133 | $scope.isDisabled = "false"; 134 | } 135 | } 136 | else if (endpoint_name == endpoint && d.uriPath == path && value.waitingForResponse) { 137 | d.show = true; 138 | } 139 | 140 | })[0]; 141 | }); 142 | 143 | }, function (data, status) { 144 | console.log('Error!!', status, data); 145 | }); 146 | } 147 | }, 1000); 148 | }); -------------------------------------------------------------------------------- /src/main/webapp/js/app/resourceModule/ResourcesDirective.js: -------------------------------------------------------------------------------- 1 | angular.module('App.directives', []); 2 | angular.module('App.directives').directive('ngSuccess', function () { 3 | return function (scope, element, attrs) { 4 | var button = angular.element(element); 5 | $(button).popover({ 6 | template: '', 16 | content: "", 17 | html: true 18 | }); 19 | }; 20 | 21 | }); 22 | angular.module('App').directive('ngError', function () { 23 | return function (scope, element, attrs) { 24 | var button = angular.element(element); 25 | $(button).popover({ 26 | template: '', 36 | content: "" 37 | }); 38 | }; 39 | }); 40 | angular.module('App').directive('ngAction', function () { 41 | return function (scope, element, attrs) { 42 | var editable_clicked = angular.element(element); 43 | $(editable_clicked).editable({ 44 | title: 'ENTER YOUR COMMAND', 45 | value: '', 46 | pk: 1, 47 | type: 'textarea', 48 | emptytext: 'action', 49 | emptyclass: '', 50 | rows: 2, 51 | tpl: '' 52 | }); 53 | }; 54 | }); 55 | 56 | angular.module('App').directive('ngConfirmClick', [ 57 | function () { 58 | return { 59 | link: function (scope, element, attr) { 60 | var msg = attr.ngConfirmClick || "Are you sure?"; 61 | var clickAction = attr.confirmedClick; 62 | element.bind('click', function (event) { 63 | if (window.confirm(msg)) { 64 | scope.$eval(clickAction) 65 | } 66 | }); 67 | } 68 | }; 69 | }]) -------------------------------------------------------------------------------- /src/main/webapp/js/app/resourceModule/ResourcesService.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | angular.module('App.services', ['ngResource']); 19 | angular.module('App.services').factory('Endpoints', function ($resource) { 20 | return $resource('webapi/endpoints/:endpoint_name/:url_path', { 21 | endpoint_name: '@endpoint_name', 22 | url_path: '@url_path' 23 | }, { 24 | update: { 25 | method: 'PUT', 26 | headers: {'Content-Type': 'text/plain'} 27 | }, 28 | set: { 29 | method: 'POST', 30 | headers: {'Content-Type': 'text/plain'} 31 | }, 32 | remove: { 33 | method: 'DELETE' 34 | } 35 | }); 36 | }); 37 | angular.module('App.services').factory('GetValues', function ($http, $q) { 38 | return { 39 | getValues: function (endpoint_name) { 40 | var deferred = $q.defer(); 41 | $http.get('webapi/endpoints/' + endpoint_name + '/values') 42 | .success(function (data) { 43 | deferred.resolve(data); 44 | }); 45 | return deferred.promise; 46 | } 47 | }; 48 | }); 49 | angular.module('App.services').factory('Configuration', function ($http) { 50 | return { 51 | getConfiguration: function () { 52 | return $http.get('webapi/configuration'); 53 | } 54 | }; 55 | }); 56 | angular.module('App.services').factory('ConnectionStatus', function ($http) { 57 | return { 58 | getStatus: function () { 59 | return $http.get('webapi/mbedclient'); 60 | } 61 | }; 62 | }); 63 | angular.module('App.services').factory('Request', function ($http) { 64 | return { 65 | sendRequest: function (name, path) { 66 | return $http.get('webapi/endpoints/' + name + '/request' + path); 67 | } 68 | }; 69 | }); -------------------------------------------------------------------------------- /src/main/webapp/js/app/resourceModule/app.js: -------------------------------------------------------------------------------- 1 | angular.module('App', 2 | ['App.controllers', 3 | 'App.services', 4 | 'App.directives']); -------------------------------------------------------------------------------- /src/main/webapp/lib/angular-moment-v0.10.2/angular-moment.min.js: -------------------------------------------------------------------------------- 1 | "format amd"; 2 | !function () { 3 | "use strict"; 4 | function a(a, b) { 5 | return a.module("angularMoment", []).constant("angularMomentConfig", { 6 | preprocess: null, 7 | timezone: "", 8 | format: null, 9 | statefulFilters: !0 10 | }).constant("moment", b).constant("amTimeAgoConfig", { 11 | withoutSuffix: !1, 12 | serverTime: null, 13 | titleFormat: null, 14 | fullDateThreshold: null, 15 | fullDateFormat: null 16 | }).directive("amTimeAgo", ["$window", "moment", "amMoment", "amTimeAgoConfig", "angularMomentConfig", function (b, c, d, e, f) { 17 | return function (g, h, i) { 18 | function j() { 19 | var a; 20 | if (p)a = p; else if (e.serverTime) { 21 | var b = (new Date).getTime(), d = b - w + e.serverTime; 22 | a = c(d) 23 | } else a = c(); 24 | return a 25 | } 26 | 27 | function k() { 28 | q && (b.clearTimeout(q), q = null) 29 | } 30 | 31 | function l(a) { 32 | var c = j().diff(a, "day"), d = u && c >= u; 33 | if (h.text(d ? a.format(v) : a.from(j(), s)), t && !h.attr("title") && h.attr("title", a.local().format(t)), !d) { 34 | var e = Math.abs(j().diff(a, "minute")), f = 3600; 35 | 1 > e ? f = 1 : 60 > e ? f = 30 : 180 > e && (f = 300), q = b.setTimeout(function () { 36 | l(a) 37 | }, 1e3 * f) 38 | } 39 | } 40 | 41 | function m(a) { 42 | z && h.attr("datetime", a) 43 | } 44 | 45 | function n() { 46 | if (k(), o) { 47 | var a = d.preprocessDate(o, x, r); 48 | l(a), m(a.toISOString()) 49 | } 50 | } 51 | 52 | var o, p, q = null, r = f.format, s = e.withoutSuffix, t = e.titleFormat, u = e.fullDateThreshold, v = e.fullDateFormat, w = (new Date).getTime(), x = f.preprocess, y = i.amTimeAgo, z = "TIME" === h[0].nodeName.toUpperCase(); 53 | g.$watch(y, function (a) { 54 | return "undefined" == typeof a || null === a || "" === a ? (k(), void(o && (h.text(""), m(""), o = null))) : (o = a, void n()) 55 | }), a.isDefined(i.amFrom) && g.$watch(i.amFrom, function (a) { 56 | p = "undefined" == typeof a || null === a || "" === a ? null : c(a), n() 57 | }), a.isDefined(i.amWithoutSuffix) && g.$watch(i.amWithoutSuffix, function (a) { 58 | "boolean" == typeof a ? (s = a, n()) : s = e.withoutSuffix 59 | }), i.$observe("amFormat", function (a) { 60 | "undefined" != typeof a && (r = a, n()) 61 | }), i.$observe("amPreprocess", function (a) { 62 | x = a, n() 63 | }), i.$observe("amFullDateThreshold", function (a) { 64 | u = a, n() 65 | }), i.$observe("amFullDateFormat", function (a) { 66 | v = a, n() 67 | }), g.$on("$destroy", function () { 68 | k() 69 | }), g.$on("amMoment:localeChanged", function () { 70 | n() 71 | }) 72 | } 73 | }]).service("amMoment", ["moment", "$rootScope", "$log", "angularMomentConfig", function (b, c, d, e) { 74 | this.preprocessors = {utc: b.utc, unix: b.unix}, this.changeLocale = function (d, e) { 75 | var f = b.locale(d, e); 76 | return a.isDefined(d) && c.$broadcast("amMoment:localeChanged"), f 77 | }, this.changeTimezone = function (a) { 78 | e.timezone = a, c.$broadcast("amMoment:timezoneChanged") 79 | }, this.preprocessDate = function (c, f, g) { 80 | return a.isUndefined(f) && (f = e.preprocess), this.preprocessors[f] ? this.preprocessors[f](c, g) : (f && d.warn("angular-moment: Ignoring unsupported value for preprocess: " + f), !isNaN(parseFloat(c)) && isFinite(c) ? b(parseInt(c, 10)) : b(c, g)) 81 | }, this.applyTimezone = function (a, b) { 82 | return (b = b || e.timezone) ? (b.match(/Z|[+-]\d\d:?\d\d/gi) ? a = a.utcOffset(b) : a.tz ? a = a.tz(b) : d.warn("angular-moment: named timezone specified but moment.tz() is undefined. Did you forget to include moment-timezone.js?"), a) : a 83 | } 84 | }]).filter("amCalendar", ["moment", "amMoment", "angularMomentConfig", function (a, b, c) { 85 | function d(c, d, e) { 86 | if ("undefined" == typeof c || null === c)return ""; 87 | c = b.preprocessDate(c, d); 88 | var f = a(c); 89 | return f.isValid() ? b.applyTimezone(f, e).calendar() : "" 90 | } 91 | 92 | return d.$stateful = c.statefulFilters, d 93 | }]).filter("amDifference", ["moment", "amMoment", "angularMomentConfig", function (a, b, c) { 94 | function d(c, d, e, f, g, h) { 95 | if ("undefined" == typeof c || null === c)return ""; 96 | c = b.preprocessDate(c, g); 97 | var i = a(c); 98 | if (!i.isValid())return ""; 99 | var j; 100 | if ("undefined" == typeof d || null === d)j = a(); else if (d = b.preprocessDate(d, h), j = a(d), !j.isValid())return ""; 101 | return b.applyTimezone(i).diff(b.applyTimezone(j), e, f) 102 | } 103 | 104 | return d.$stateful = c.statefulFilters, d 105 | }]).filter("amDateFormat", ["moment", "amMoment", "angularMomentConfig", function (a, b, c) { 106 | function d(c, d, e, f) { 107 | if ("undefined" == typeof c || null === c)return ""; 108 | c = b.preprocessDate(c, e); 109 | var g = a(c); 110 | return g.isValid() ? b.applyTimezone(g, f).format(d) : "" 111 | } 112 | 113 | return d.$stateful = c.statefulFilters, d 114 | }]).filter("amDurationFormat", ["moment", "angularMomentConfig", function (a, b) { 115 | function c(b, c, d) { 116 | return "undefined" == typeof b || null === b ? "" : a.duration(b, c).humanize(d) 117 | } 118 | 119 | return c.$stateful = b.statefulFilters, c 120 | }]).filter("amTimeAgo", ["moment", "amMoment", "angularMomentConfig", function (a, b, c) { 121 | function d(c, d, e, f) { 122 | var g, h; 123 | return "undefined" == typeof c || null === c ? "" : (c = b.preprocessDate(c, d), g = a(c), g.isValid() ? (h = a(f), "undefined" != typeof f && h.isValid() ? b.applyTimezone(g).from(h, e) : b.applyTimezone(g).fromNow(e)) : "") 124 | } 125 | 126 | return d.$stateful = c.statefulFilters, d 127 | }]) 128 | } 129 | 130 | "function" == typeof define && define.amd ? define(["angular", "moment"], a) : "undefined" != typeof module && module && module.exports ? (a(angular, require("moment")), module.exports = "angularMoment") : a(angular, ("undefined" != typeof global ? global : window).moment) 131 | }(); 132 | //# sourceMappingURL=angular-moment.min.js.map -------------------------------------------------------------------------------- /src/main/webapp/lib/angularjs-v1.4.3/angular-resource.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.4.3 3 | (c) 2010-2015 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(I,d,B){'use strict';function D(f,q){q=q||{};d.forEach(q,function(d,h){delete q[h]});for(var h in f)!f.hasOwnProperty(h)||"$"===h.charAt(0)&&"$"===h.charAt(1)||(q[h]=f[h]);return q}var x=d.$$minErr("$resource"),C=/^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;d.module("ngResource",["ng"]).provider("$resource",function(){var f=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}}; 7 | this.$get=["$http","$q",function(q,h){function u(d,g){this.template=d;this.defaults=s({},f.defaults,g);this.urlParams={}}function w(y,g,l,m){function c(b,k){var c={};k=s({},g,k);r(k,function(a,k){v(a)&&(a=a());var d;if(a&&a.charAt&&"@"==a.charAt(0)){d=b;var e=a.substr(1);if(null==e||""===e||"hasOwnProperty"===e||!C.test("."+e))throw x("badmember",e);for(var e=e.split("."),n=0,g=e.length;n