Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:70a6082c1bf7, committed 2016-07-14
- Comitter:
- ShaneKirkbride
- Date:
- Thu Jul 14 20:38:18 2016 +0000
- Child:
- 1:99c58a942425
- Commit message:
- first commit. Rest example working
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FP.cpp Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,597 @@
+/**
+ * @file FP.cpp
+ * @brief Core Utility - Templated Function Pointer Class
+ * @author sam grove
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FP.h"
+#include <stdint.h>
+
+template<class retT, class argT>
+FP<retT, argT>::FP()
+{
+ obj_callback = 0;
+ c_callback = 0;
+}
+
+template<class retT, class argT>
+bool FP<retT, argT>::attached()
+{
+ return obj_callback || c_callback;
+}
+
+
+template<class retT, class argT>
+void FP<retT, argT>::detach()
+{
+ obj_callback = 0;
+ c_callback = 0;
+}
+
+
+template<class retT, class argT>
+void FP<retT, argT>::attach(retT (*function)(argT))
+{
+ c_callback = function;
+}
+
+template<class retT, class argT>
+retT FP<retT, argT>::operator()(argT arg) const
+{
+ if( 0 != c_callback )
+ {
+ return obj_callback ? (obj_callback->*method_callback)(arg) : (*c_callback)(arg);
+ }
+ return (retT)0;
+}
+
+// pre-define the types for the linker
+template class FP<void,char>;
+template class FP<void,char*>;
+template class FP<void,int8_t>;
+template class FP<void,int8_t*>;
+template class FP<void,uint8_t>;
+template class FP<void,uint8_t*>;
+template class FP<void,int16_t>;
+template class FP<void,int16_t*>;
+template class FP<void,uint16_t>;
+template class FP<void,uint16_t*>;
+template class FP<void,int32_t>;
+template class FP<void,int32_t*>;
+template class FP<void,uint32_t>;
+template class FP<void,uint32_t*>;
+template class FP<void,int64_t>;
+template class FP<void,int64_t*>;
+template class FP<void,uint64_t>;
+template class FP<void,uint64_t*>;
+template class FP<void,bool>;
+template class FP<void,bool*>;
+template class FP<void,float>;
+template class FP<void,float*>;
+template class FP<void,double>;
+template class FP<void,double*>;
+template class FP<void,void*>;
+
+template class FP<int8_t,char>;
+template class FP<int8_t,char*>;
+template class FP<int8_t,int8_t>;
+template class FP<int8_t,int8_t*>;
+template class FP<int8_t,uint8_t>;
+template class FP<int8_t,uint8_t*>;
+template class FP<int8_t,int16_t>;
+template class FP<int8_t,int16_t*>;
+template class FP<int8_t,uint16_t>;
+template class FP<int8_t,uint16_t*>;
+template class FP<int8_t,int32_t>;
+template class FP<int8_t,int32_t*>;
+template class FP<int8_t,uint32_t>;
+template class FP<int8_t,uint32_t*>;
+template class FP<int8_t,int64_t>;
+template class FP<int8_t,int64_t*>;
+template class FP<int8_t,uint64_t>;
+template class FP<int8_t,uint64_t*>;
+template class FP<int8_t,bool>;
+template class FP<int8_t,bool*>;
+template class FP<int8_t,float>;
+template class FP<int8_t,float*>;
+template class FP<int8_t,double>;
+template class FP<int8_t,double*>;
+
+template class FP<int8_t*,char>;
+template class FP<int8_t*,char*>;
+template class FP<int8_t*,int8_t>;
+template class FP<int8_t*,int8_t*>;
+template class FP<int8_t*,uint8_t>;
+template class FP<int8_t*,uint8_t*>;
+template class FP<int8_t*,int16_t>;
+template class FP<int8_t*,int16_t*>;
+template class FP<int8_t*,uint16_t>;
+template class FP<int8_t*,uint16_t*>;
+template class FP<int8_t*,int32_t>;
+template class FP<int8_t*,int32_t*>;
+template class FP<int8_t*,uint32_t>;
+template class FP<int8_t*,uint32_t*>;
+template class FP<int8_t*,int64_t>;
+template class FP<int8_t*,int64_t*>;
+template class FP<int8_t*,uint64_t>;
+template class FP<int8_t*,uint64_t*>;
+template class FP<int8_t*,bool>;
+template class FP<int8_t*,bool*>;
+template class FP<int8_t*,float>;
+template class FP<int8_t*,float*>;
+template class FP<int8_t*,double>;
+template class FP<int8_t*,double*>;
+
+template class FP<uint8_t,char>;
+template class FP<uint8_t,char*>;
+template class FP<uint8_t,int8_t>;
+template class FP<uint8_t,int8_t*>;
+template class FP<uint8_t,uint8_t>;
+template class FP<uint8_t,uint8_t*>;
+template class FP<uint8_t,int16_t>;
+template class FP<uint8_t,int16_t*>;
+template class FP<uint8_t,uint16_t>;
+template class FP<uint8_t,uint16_t*>;
+template class FP<uint8_t,int32_t>;
+template class FP<uint8_t,int32_t*>;
+template class FP<uint8_t,uint32_t>;
+template class FP<uint8_t,uint32_t*>;
+template class FP<uint8_t,int64_t>;
+template class FP<uint8_t,int64_t*>;
+template class FP<uint8_t,uint64_t>;
+template class FP<uint8_t,uint64_t*>;
+template class FP<uint8_t,bool>;
+template class FP<uint8_t,bool*>;
+template class FP<uint8_t,float>;
+template class FP<uint8_t,float*>;
+template class FP<uint8_t,double>;
+template class FP<uint8_t,double*>;
+
+template class FP<uint8_t*,char>;
+template class FP<uint8_t*,char*>;
+template class FP<uint8_t*,int8_t>;
+template class FP<uint8_t*,int8_t*>;
+template class FP<uint8_t*,uint8_t>;
+template class FP<uint8_t*,uint8_t*>;
+template class FP<uint8_t*,int16_t>;
+template class FP<uint8_t*,int16_t*>;
+template class FP<uint8_t*,uint16_t>;
+template class FP<uint8_t*,uint16_t*>;
+template class FP<uint8_t*,int32_t>;
+template class FP<uint8_t*,int32_t*>;
+template class FP<uint8_t*,uint32_t>;
+template class FP<uint8_t*,uint32_t*>;
+template class FP<uint8_t*,int64_t>;
+template class FP<uint8_t*,int64_t*>;
+template class FP<uint8_t*,uint64_t>;
+template class FP<uint8_t*,uint64_t*>;
+template class FP<uint8_t*,bool>;
+template class FP<uint8_t*,bool*>;
+template class FP<uint8_t*,float>;
+template class FP<uint8_t*,float*>;
+template class FP<uint8_t*,double>;
+template class FP<uint8_t*,double*>;
+
+template class FP<int16_t,char>;
+template class FP<int16_t,char*>;
+template class FP<int16_t,int8_t>;
+template class FP<int16_t,int8_t*>;
+template class FP<int16_t,uint8_t>;
+template class FP<int16_t,uint8_t*>;
+template class FP<int16_t,int16_t>;
+template class FP<int16_t,int16_t*>;
+template class FP<int16_t,uint16_t>;
+template class FP<int16_t,uint16_t*>;
+template class FP<int16_t,int32_t>;
+template class FP<int16_t,int32_t*>;
+template class FP<int16_t,uint32_t>;
+template class FP<int16_t,uint32_t*>;
+template class FP<int16_t,int64_t>;
+template class FP<int16_t,int64_t*>;
+template class FP<int16_t,uint64_t>;
+template class FP<int16_t,uint64_t*>;
+template class FP<int16_t,bool>;
+template class FP<int16_t,bool*>;
+template class FP<int16_t,float>;
+template class FP<int16_t,float*>;
+template class FP<int16_t,double>;
+template class FP<int16_t,double*>;
+
+template class FP<int16_t*,char>;
+template class FP<int16_t*,char*>;
+template class FP<int16_t*,int8_t>;
+template class FP<int16_t*,int8_t*>;
+template class FP<int16_t*,uint8_t>;
+template class FP<int16_t*,uint8_t*>;
+template class FP<int16_t*,int16_t>;
+template class FP<int16_t*,int16_t*>;
+template class FP<int16_t*,uint16_t>;
+template class FP<int16_t*,uint16_t*>;
+template class FP<int16_t*,int32_t>;
+template class FP<int16_t*,int32_t*>;
+template class FP<int16_t*,uint32_t>;
+template class FP<int16_t*,uint32_t*>;
+template class FP<int16_t*,int64_t>;
+template class FP<int16_t*,int64_t*>;
+template class FP<int16_t*,uint64_t>;
+template class FP<int16_t*,uint64_t*>;
+template class FP<int16_t*,bool>;
+template class FP<int16_t*,bool*>;
+template class FP<int16_t*,float>;
+template class FP<int16_t*,float*>;
+template class FP<int16_t*,double>;
+template class FP<int16_t*,double*>;
+
+template class FP<uint16_t,char>;
+template class FP<uint16_t,char*>;
+template class FP<uint16_t,int8_t>;
+template class FP<uint16_t,int8_t*>;
+template class FP<uint16_t,uint8_t>;
+template class FP<uint16_t,uint8_t*>;
+template class FP<uint16_t,int16_t>;
+template class FP<uint16_t,int16_t*>;
+template class FP<uint16_t,uint16_t>;
+template class FP<uint16_t,uint16_t*>;
+template class FP<uint16_t,int32_t>;
+template class FP<uint16_t,int32_t*>;
+template class FP<uint16_t,uint32_t>;
+template class FP<uint16_t,uint32_t*>;
+template class FP<uint16_t,int64_t>;
+template class FP<uint16_t,int64_t*>;
+template class FP<uint16_t,uint64_t>;
+template class FP<uint16_t,uint64_t*>;
+template class FP<uint16_t,bool>;
+template class FP<uint16_t,bool*>;
+template class FP<uint16_t,float>;
+template class FP<uint16_t,float*>;
+template class FP<uint16_t,double>;
+template class FP<uint16_t,double*>;
+
+template class FP<uint16_t*,char>;
+template class FP<uint16_t*,char*>;
+template class FP<uint16_t*,int8_t>;
+template class FP<uint16_t*,int8_t*>;
+template class FP<uint16_t*,uint8_t>;
+template class FP<uint16_t*,uint8_t*>;
+template class FP<uint16_t*,int16_t>;
+template class FP<uint16_t*,int16_t*>;
+template class FP<uint16_t*,uint16_t>;
+template class FP<uint16_t*,uint16_t*>;
+template class FP<uint16_t*,int32_t>;
+template class FP<uint16_t*,int32_t*>;
+template class FP<uint16_t*,uint32_t>;
+template class FP<uint16_t*,uint32_t*>;
+template class FP<uint16_t*,int64_t>;
+template class FP<uint16_t*,int64_t*>;
+template class FP<uint16_t*,uint64_t>;
+template class FP<uint16_t*,uint64_t*>;
+template class FP<uint16_t*,bool>;
+template class FP<uint16_t*,bool*>;
+template class FP<uint16_t*,float>;
+template class FP<uint16_t*,float*>;
+template class FP<uint16_t*,double>;
+template class FP<uint16_t*,double*>;
+
+template class FP<int32_t,char>;
+template class FP<int32_t,char*>;
+template class FP<int32_t,int8_t>;
+template class FP<int32_t,int8_t*>;
+template class FP<int32_t,uint8_t>;
+template class FP<int32_t,uint8_t*>;
+template class FP<int32_t,int16_t>;
+template class FP<int32_t,int16_t*>;
+template class FP<int32_t,uint16_t>;
+template class FP<int32_t,uint16_t*>;
+template class FP<int32_t,int32_t>;
+template class FP<int32_t,int32_t*>;
+template class FP<int32_t,uint32_t>;
+template class FP<int32_t,uint32_t*>;
+template class FP<int32_t,int64_t>;
+template class FP<int32_t,int64_t*>;
+template class FP<int32_t,uint64_t>;
+template class FP<int32_t,uint64_t*>;
+template class FP<int32_t,bool>;
+template class FP<int32_t,bool*>;
+template class FP<int32_t,float>;
+template class FP<int32_t,float*>;
+template class FP<int32_t,double>;
+template class FP<int32_t,double*>;
+
+template class FP<int32_t*,char>;
+template class FP<int32_t*,char*>;
+template class FP<int32_t*,int8_t>;
+template class FP<int32_t*,int8_t*>;
+template class FP<int32_t*,uint8_t>;
+template class FP<int32_t*,uint8_t*>;
+template class FP<int32_t*,int16_t>;
+template class FP<int32_t*,int16_t*>;
+template class FP<int32_t*,uint16_t>;
+template class FP<int32_t*,uint16_t*>;
+template class FP<int32_t*,int32_t>;
+template class FP<int32_t*,int32_t*>;
+template class FP<int32_t*,uint32_t>;
+template class FP<int32_t*,uint32_t*>;
+template class FP<int32_t*,int64_t>;
+template class FP<int32_t*,int64_t*>;
+template class FP<int32_t*,uint64_t>;
+template class FP<int32_t*,uint64_t*>;
+template class FP<int32_t*,bool>;
+template class FP<int32_t*,bool*>;
+template class FP<int32_t*,float>;
+template class FP<int32_t*,float*>;
+template class FP<int32_t*,double>;
+template class FP<int32_t*,double*>;
+
+template class FP<uint32_t,char>;
+template class FP<uint32_t,char*>;
+template class FP<uint32_t,int8_t>;
+template class FP<uint32_t,int8_t*>;
+template class FP<uint32_t,uint8_t>;
+template class FP<uint32_t,uint8_t*>;
+template class FP<uint32_t,int16_t>;
+template class FP<uint32_t,int16_t*>;
+template class FP<uint32_t,uint16_t>;
+template class FP<uint32_t,uint16_t*>;
+template class FP<uint32_t,int32_t>;
+template class FP<uint32_t,int32_t*>;
+template class FP<uint32_t,uint32_t>;
+template class FP<uint32_t,uint32_t*>;
+template class FP<uint32_t,int64_t>;
+template class FP<uint32_t,int64_t*>;
+template class FP<uint32_t,uint64_t>;
+template class FP<uint32_t,uint64_t*>;
+template class FP<uint32_t,bool>;
+template class FP<uint32_t,bool*>;
+template class FP<uint32_t,float>;
+template class FP<uint32_t,float*>;
+template class FP<uint32_t,double>;
+template class FP<uint32_t,double*>;
+
+template class FP<uint32_t*,char>;
+template class FP<uint32_t*,char*>;
+template class FP<uint32_t*,int8_t>;
+template class FP<uint32_t*,int8_t*>;
+template class FP<uint32_t*,uint8_t>;
+template class FP<uint32_t*,uint8_t*>;
+template class FP<uint32_t*,int16_t>;
+template class FP<uint32_t*,int16_t*>;
+template class FP<uint32_t*,uint16_t>;
+template class FP<uint32_t*,uint16_t*>;
+template class FP<uint32_t*,int32_t>;
+template class FP<uint32_t*,int32_t*>;
+template class FP<uint32_t*,uint32_t>;
+template class FP<uint32_t*,uint32_t*>;
+template class FP<uint32_t*,int64_t>;
+template class FP<uint32_t*,int64_t*>;
+template class FP<uint32_t*,uint64_t>;
+template class FP<uint32_t*,uint64_t*>;
+template class FP<uint32_t*,bool>;
+template class FP<uint32_t*,bool*>;
+template class FP<uint32_t*,float>;
+template class FP<uint32_t*,float*>;
+template class FP<uint32_t*,double>;
+template class FP<uint32_t*,double*>;
+
+template class FP<int64_t,char>;
+template class FP<int64_t,char*>;
+template class FP<int64_t,int8_t>;
+template class FP<int64_t,int8_t*>;
+template class FP<int64_t,uint8_t>;
+template class FP<int64_t,uint8_t*>;
+template class FP<int64_t,int16_t>;
+template class FP<int64_t,int16_t*>;
+template class FP<int64_t,uint16_t>;
+template class FP<int64_t,uint16_t*>;
+template class FP<int64_t,int32_t>;
+template class FP<int64_t,int32_t*>;
+template class FP<int64_t,uint32_t>;
+template class FP<int64_t,uint32_t*>;
+template class FP<int64_t,int64_t>;
+template class FP<int64_t,int64_t*>;
+template class FP<int64_t,uint64_t>;
+template class FP<int64_t,uint64_t*>;
+template class FP<int64_t,bool>;
+template class FP<int64_t,bool*>;
+template class FP<int64_t,float>;
+template class FP<int64_t,float*>;
+template class FP<int64_t,double>;
+template class FP<int64_t,double*>;
+
+template class FP<int64_t*,char>;
+template class FP<int64_t*,char*>;
+template class FP<int64_t*,int8_t>;
+template class FP<int64_t*,int8_t*>;
+template class FP<int64_t*,uint8_t>;
+template class FP<int64_t*,uint8_t*>;
+template class FP<int64_t*,int16_t>;
+template class FP<int64_t*,int16_t*>;
+template class FP<int64_t*,uint16_t>;
+template class FP<int64_t*,uint16_t*>;
+template class FP<int64_t*,int32_t>;
+template class FP<int64_t*,int32_t*>;
+template class FP<int64_t*,uint32_t>;
+template class FP<int64_t*,uint32_t*>;
+template class FP<int64_t*,int64_t>;
+template class FP<int64_t*,int64_t*>;
+template class FP<int64_t*,uint64_t>;
+template class FP<int64_t*,uint64_t*>;
+template class FP<int64_t*,bool>;
+template class FP<int64_t*,bool*>;
+template class FP<int64_t*,float>;
+template class FP<int64_t*,float*>;
+template class FP<int64_t*,double>;
+template class FP<int64_t*,double*>;
+
+template class FP<uint64_t,char>;
+template class FP<uint64_t,char*>;
+template class FP<uint64_t,int8_t>;
+template class FP<uint64_t,int8_t*>;
+template class FP<uint64_t,uint8_t>;
+template class FP<uint64_t,uint8_t*>;
+template class FP<uint64_t,int16_t>;
+template class FP<uint64_t,int16_t*>;
+template class FP<uint64_t,uint16_t>;
+template class FP<uint64_t,uint16_t*>;
+template class FP<uint64_t,int32_t>;
+template class FP<uint64_t,int32_t*>;
+template class FP<uint64_t,uint32_t>;
+template class FP<uint64_t,uint32_t*>;
+template class FP<uint64_t,int64_t>;
+template class FP<uint64_t,int64_t*>;
+template class FP<uint64_t,uint64_t>;
+template class FP<uint64_t,uint64_t*>;
+template class FP<uint64_t,bool>;
+template class FP<uint64_t,bool*>;
+template class FP<uint64_t,float>;
+template class FP<uint64_t,float*>;
+template class FP<uint64_t,double>;
+template class FP<uint64_t,double*>;
+
+template class FP<uint64_t*,char>;
+template class FP<uint64_t*,char*>;
+template class FP<uint64_t*,int8_t>;
+template class FP<uint64_t*,int8_t*>;
+template class FP<uint64_t*,uint8_t>;
+template class FP<uint64_t*,uint8_t*>;
+template class FP<uint64_t*,int16_t>;
+template class FP<uint64_t*,int16_t*>;
+template class FP<uint64_t*,uint16_t>;
+template class FP<uint64_t*,uint16_t*>;
+template class FP<uint64_t*,int32_t>;
+template class FP<uint64_t*,int32_t*>;
+template class FP<uint64_t*,uint32_t>;
+template class FP<uint64_t*,uint32_t*>;
+template class FP<uint64_t*,int64_t>;
+template class FP<uint64_t*,int64_t*>;
+template class FP<uint64_t*,uint64_t>;
+template class FP<uint64_t*,uint64_t*>;
+template class FP<uint64_t*,bool>;
+template class FP<uint64_t*,bool*>;
+template class FP<uint64_t*,float>;
+template class FP<uint64_t*,float*>;
+template class FP<uint64_t*,double>;
+template class FP<uint64_t*,double*>;
+
+template class FP<float,char>;
+template class FP<float,char*>;
+template class FP<float,int8_t>;
+template class FP<float,int8_t*>;
+template class FP<float,uint8_t>;
+template class FP<float,uint8_t*>;
+template class FP<float,int16_t>;
+template class FP<float,int16_t*>;
+template class FP<float,uint16_t>;
+template class FP<float,uint16_t*>;
+template class FP<float,int32_t>;
+template class FP<float,int32_t*>;
+template class FP<float,uint32_t>;
+template class FP<float,uint32_t*>;
+template class FP<float,int64_t>;
+template class FP<float,int64_t*>;
+template class FP<float,uint64_t>;
+template class FP<float,uint64_t*>;
+template class FP<float,bool>;
+template class FP<float,bool*>;
+template class FP<float,float>;
+template class FP<float,float*>;
+template class FP<float,double>;
+template class FP<float,double*>;
+
+template class FP<float*,char>;
+template class FP<float*,char*>;
+template class FP<float*,int8_t>;
+template class FP<float*,int8_t*>;
+template class FP<float*,uint8_t>;
+template class FP<float*,uint8_t*>;
+template class FP<float*,int16_t>;
+template class FP<float*,int16_t*>;
+template class FP<float*,uint16_t>;
+template class FP<float*,uint16_t*>;
+template class FP<float*,int32_t>;
+template class FP<float*,int32_t*>;
+template class FP<float*,uint32_t>;
+template class FP<float*,uint32_t*>;
+template class FP<float*,int64_t>;
+template class FP<float*,int64_t*>;
+template class FP<float*,uint64_t>;
+template class FP<float*,uint64_t*>;
+template class FP<float*,bool>;
+template class FP<float*,bool*>;
+template class FP<float*,float>;
+template class FP<float*,float*>;
+template class FP<float*,double>;
+template class FP<float*,double*>;
+
+template class FP<double,char>;
+template class FP<double,char*>;
+template class FP<double,int8_t>;
+template class FP<double,int8_t*>;
+template class FP<double,uint8_t>;
+template class FP<double,uint8_t*>;
+template class FP<double,int16_t>;
+template class FP<double,int16_t*>;
+template class FP<double,uint16_t>;
+template class FP<double,uint16_t*>;
+template class FP<double,int32_t>;
+template class FP<double,int32_t*>;
+template class FP<double,uint32_t>;
+template class FP<double,uint32_t*>;
+template class FP<double,int64_t>;
+template class FP<double,int64_t*>;
+template class FP<double,uint64_t>;
+template class FP<double,uint64_t*>;
+template class FP<double,bool>;
+template class FP<double,bool*>;
+template class FP<double,float>;
+template class FP<double,float*>;
+template class FP<double,double>;
+template class FP<double,double*>;
+
+template class FP<double*,char>;
+template class FP<double*,char*>;
+template class FP<double*,int8_t>;
+template class FP<double*,int8_t*>;
+template class FP<double*,uint8_t>;
+template class FP<double*,uint8_t*>;
+template class FP<double*,int16_t>;
+template class FP<double*,int16_t*>;
+template class FP<double*,uint16_t>;
+template class FP<double*,uint16_t*>;
+template class FP<double*,int32_t>;
+template class FP<double*,int32_t*>;
+template class FP<double*,uint32_t>;
+template class FP<double*,uint32_t*>;
+template class FP<double*,int64_t>;
+template class FP<double*,int64_t*>;
+template class FP<double*,uint64_t>;
+template class FP<double*,uint64_t*>;
+template class FP<double*,bool>;
+template class FP<double*,bool*>;
+template class FP<double*,float>;
+template class FP<double*,float*>;
+template class FP<double*,double>;
+template class FP<double*,double*>;
+
+template class FP<char, char>;
+template class FP<char, char*>;
+template class FP<char, const char*>;
+
+template class FP<char*, char>;
+template class FP<char*, char*>;
+template class FP<char*, const char*>;
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FP.h Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,187 @@
+/**
+ * @file FP.h
+ * @brief Core Utility - Templated Function Pointer Class
+ * @author sam grove
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FP_H
+#define FP_H
+
+/** Example using the FP Class with global functions
+ * @code
+ * #include "mbed.h"
+ * #include "FP.h"
+ *
+ * FP<void,bool>fp;
+ * DigitalOut myled(LED1);
+ *
+ * void handler(bool value)
+ * {
+ * myled = value;
+ * return;
+ * }
+ *
+ * int main()
+ * {
+ * fp.attach(&handler);
+ *
+ * while(1)
+ * {
+ * fp(1);
+ * wait(0.2);
+ * fp(0);
+ * wait(0.2);
+ * }
+ * }
+ * @endcode
+ */
+
+/** Example using the FP Class with different class member functions
+ * @code
+ * #include "mbed.h"
+ * #include "FP.h"
+ *
+ * FP<void,bool>fp;
+ * DigitalOut myled(LED4);
+ *
+ * class Wrapper
+ * {
+ * public:
+ * Wrapper(){}
+ *
+ * void handler(bool value)
+ * {
+ * myled = value;
+ * return;
+ * }
+ * };
+ *
+ * int main()
+ * {
+ * Wrapper wrapped;
+ * fp.attach(&wrapped, &Wrapper::handler);
+ *
+ * while(1)
+ * {
+ * fp(1);
+ * wait(0.2);
+ * fp(0);
+ * wait(0.2);
+ * }
+ * }
+ * @endcode
+ */
+
+ /** Example using the FP Class with member FP and member function
+ * @code
+ * #include "mbed.h"
+ * #include "FP.h"
+ *
+ * DigitalOut myled(LED2);
+ *
+ * class Wrapper
+ * {
+ * public:
+ * Wrapper()
+ * {
+ * fp.attach(this, &Wrapper::handler);
+ * }
+ *
+ * void handler(bool value)
+ * {
+ * myled = value;
+ * return;
+ * }
+ *
+ * FP<void,bool>fp;
+ * };
+ *
+ * int main()
+ * {
+ * Wrapper wrapped;
+ *
+ * while(1)
+ * {
+ * wrapped.fp(1);
+ * wait(0.2);
+ * wrapped.fp(0);
+ * wait(0.2);
+ * }
+ * }
+ * @endcode
+ */
+
+/**
+ * @class FP
+ * @brief API abstraction for a Function Pointers
+ */
+template<class retT, class argT>
+class FP
+{
+public:
+ /** Create the FP object
+ */
+ FP();
+
+ /** Add a callback function to the class
+ * @param item - Address of the initialized class
+ * @param member - Address of the member function (dont forget the scope that the function is defined in)
+ */
+ template<class T>
+ void attach(T *item, retT (T::*method)(argT))
+ {
+ obj_callback = (FPtrDummy *)(item);
+ method_callback = (retT (FPtrDummy::*)(argT))(method);
+ return;
+ }
+
+ /** Add a callback function to the class
+ * @param function - The address of a globally defined function
+ */
+ void attach(retT (*function)(argT));
+
+ /** Invoke the function attached to the class
+ * @param arg - An argument that is passed into the function handler that is called
+ * @return The return from the function hanlder called by this class
+ */
+ retT operator()(argT arg) const;
+
+ bool attached();
+
+ void detach();
+
+private:
+
+ // empty type used for casting
+ class FPtrDummy;
+
+ FPtrDummy *obj_callback;
+
+ /**
+ * @union Funciton
+ * @brief Member or global callback function
+ */
+ union
+ {
+ retT (*c_callback)(argT); /*!< Footprint for a global function */
+ retT (FPtrDummy::*method_callback)(argT); /*!< Footprint for a member function */
+ };
+};
+
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/STMClient.cpp Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,276 @@
+#include "STMClient.h"
+#include "millis.h"
+
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define SLIP_END 0300 // indicates end of packet
+#define SLIP_ESC 0333 // indicates byte stuffing
+#define SLIP_ESC_END 0334 // ESC ESC_END means END data byte
+#define SLIP_ESC_ESC 0335 // ESC ESC_ESC means ESC data byte
+
+//===== Input
+
+// Process a received SLIP message
+STMClientPacket* STMClient::protoCompletedCb(void) {
+ // the packet starts with a STMClientPacket
+ STMClientPacket* packet = (STMClientPacket*)_proto.buf;
+ if (_debugEn) {
+ // _debug->printf("STMC: got %i @ %i:\n\r 0x%x\n\r 0x%x\n\r 0x%x\n\r", _proto.dataLen,(uint32_t)_proto.buf, packet->cmd, packet->value, packet->argc);
+
+ for (uint16_t i=8; i<_proto.dataLen; i++)
+ {
+ // _debug->printf("%x", *(uint8_t*)(_proto.buf+i));
+ }
+ //_debug->printf("\n\r");
+ }
+
+ // verify CRC
+ uint16_t crc = crc16Data(_proto.buf, _proto.dataLen-2, 0);
+ //_debug->printf("CRC: %i\n\r",crc);
+ //wait(0.5);
+ uint16_t resp_crc = *(uint16_t*)(_proto.buf+_proto.dataLen-2);
+ //_debug->printf("resp_crc: %i\n\r",resp_crc);
+ if (crc != resp_crc) {
+ DBG("STMC: Invalid CRC\n\r");
+ wait(0.5);
+
+ //return NULL; maybe the CRC isn't getting calculated correctly...
+ }
+
+ // dispatch based on command
+ if (packet->cmd == CMD_RESP_V) {
+ // value response
+ _debug->printf("RESP_V: 0x%x \n\r",packet->value);
+
+ return packet;
+ } else if (packet->cmd == CMD_RESP_CB) {
+ FP<void, void*> *fp;
+ // callback reponse
+ _debug->printf("RESP_CB: 0x%x 0x%x \n\r", packet->value, packet->argc);
+
+ fp = (FP<void, void*>*)packet->value;
+ if (fp->attached()) {
+ STMClientResponse resp(packet);
+ (*fp)(&resp);
+ }
+ return NULL;
+ } else {
+ // command (NOT IMPLEMENTED)
+ _debug->printf("CMD 0x%x Value 0x%x ??\n\r", packet->cmd, packet->value);
+ return NULL;
+ }
+}
+
+// Read all characters available on the serial input and process any messages that arrive, but
+// stop if a non-callback response comes in
+STMClientPacket *STMClient::Process() {
+ while (_serial->readable()) {
+ //value =_serial->getc(rxBuffer, 5, eSerialCb, SERIAL_EVENT_RX_ALL, '$');
+ char character=_serial->getc();
+ //value = _serial->read();
+
+ if ((int)character == SLIP_ESC) {
+ _proto.isEsc = 1;
+ } else if ((int)character == SLIP_END) {
+ STMClientPacket *packet = _proto.dataLen >= 8 ? protoCompletedCb() : 0;
+ _proto.dataLen = 0;
+ _proto.isEsc = 0;
+ if (packet != NULL) return packet;
+ } else {
+ if (_proto.isEsc) {
+ if ((int)character == SLIP_ESC_END) character = SLIP_END;
+ if ((int)character == SLIP_ESC_ESC) character = SLIP_ESC;
+ _proto.isEsc = 0;
+ }
+ if (_proto.dataLen < _proto.bufSize) {
+ _proto.buf[_proto.dataLen++] = (int)character;
+ }
+ }
+ }
+ return NULL;
+}
+
+//===== Output
+
+// Write a byte to the output stream and perform SLIP escaping
+void STMClient::write(uint8_t data) {
+ switch (data) {
+ case SLIP_END:
+ _serial->putc(SLIP_ESC);
+ _serial->putc(SLIP_ESC_END);
+ break;
+ case SLIP_ESC:
+ _serial->putc(SLIP_ESC);
+ _serial->putc(SLIP_ESC_ESC);
+ break;
+ default:
+ _serial->putc(data);
+ }
+}
+
+// Write some bytes to the output stream
+void STMClient::write(void* data, uint16_t len) {
+ uint8_t *d = (uint8_t*)data;
+ while (len--)
+ write(*d++);
+}
+
+// Start a request. cmd=command, value=address of callback pointer or first arg,
+// argc=additional argument count
+void STMClient::Request(uint16_t cmd, uint32_t value, uint16_t argc) {
+ //_debug->printf("Starting a request...\n\r");
+ //wait(0.5);
+ crc = 0;
+ _serial->putc(SLIP_END);
+
+ write(&cmd, 2);
+ crc = crc16Data((unsigned const char*)&cmd, 2, crc);
+
+ write(&argc, 2);
+ crc = crc16Data((unsigned const char*)&argc, 2, crc);
+
+ write(&value, 4);
+ crc = crc16Data((unsigned const char*)&value, 4, crc);
+}
+
+// Append a block of data as an argument to the request
+void STMClient::Request(const void* data, uint16_t len) {
+ uint8_t *d = (uint8_t*)data;
+
+ // write the length
+ write(&len, 2);
+ crc = crc16Data((unsigned const char*)&len, 2, crc);
+
+ // output the data
+ for (uint16_t l=len; l>0; l--) {
+ write(*d);
+ crc = crc16Add(*d, crc);
+ d++;
+ }
+
+ // output padding
+ uint16_t pad = (4-(len&3))&3;
+ uint8_t temp = 0;
+ while (pad--) {
+ write(temp);
+ crc = crc16Add(temp, crc);
+ }
+}
+
+/* Commented this out for now...
+// Append a block of data located in flash as an argument to the request
+void STMClient::Request(const __FlashStringHSTMper* data, uint16_t len) {
+ // write the length
+ write(&len, 2);
+ crc = crc16Data((unsigned const char*)&len, 2, crc);
+
+ // output the data
+ PGM_P p = reinterpret_cast<PGM_P>(data);
+ for (uint16_t l=len; l>0; l--) {
+ uint8_t c = pgm_read_byte(p++);
+ write(c);
+ crc = crc16Add(c, crc);
+ }
+
+ // output padding
+ uint16_t pad = (4-(len&3))&3;
+ uint8_t temp = 0;
+ while (pad--) {
+ write(temp);
+ crc = crc16Add(temp, crc);
+ }
+}
+*/
+
+// Append the final CRC to the request and finish the request
+void STMClient::Request(void) {
+ write((uint8_t*)&crc, 2);
+ _serial->putc(SLIP_END);
+}
+
+//===== Initialization
+
+void STMClient::init() {
+ _proto.buf = _protoBuf;
+ _proto.bufSize = sizeof(_protoBuf);
+ _proto.dataLen = 0;
+ _proto.isEsc = 0;
+}
+
+STMClient::STMClient(Serial* serial) :
+_serial(serial) {
+ _debugEn = false;
+ init();
+}
+
+STMClient::STMClient(Serial* serial, Serial* debug) :
+_debug(debug), _serial(serial) {
+ _debugEn = true;
+ init();
+}
+
+void STMClient::DBG(const char* info) {
+ if (_debugEn) _debug->printf(info);
+}
+
+//===== Responses
+
+// Wait for a response for a given timeout
+STMClientPacket *STMClient::WaitReturn(uint32_t timeout) {
+ uint32_t wait = millis();
+ while (millis() - wait < timeout) {
+ STMClientPacket *packet = Process();
+ if (packet != NULL) return packet;
+ }
+ return NULL;
+}
+
+//===== CRC hSTMper functions
+
+uint16_t STMClient::crc16Add(unsigned char b, uint16_t acc)
+{
+ acc ^= b;
+ acc = (acc >> 8) | (acc << 8);
+ acc ^= (acc & 0xff00) << 4;
+ acc ^= (acc >> 8) >> 4;
+ acc ^= (acc & 0xff00) >> 5;
+ return acc;
+}
+
+uint16_t STMClient::crc16Data(const unsigned char *data, uint16_t len, uint16_t acc)
+{
+ for (uint16_t i=0; i<len; i++)
+ acc = crc16Add(*data++, acc);
+ return acc;
+}
+
+//===== Basic requests built into STMClient
+
+bool STMClient::Sync(uint32_t timeout) {
+ //_debug->printf("syncing...");
+ wait(0.5);
+ // send sync request
+ Request(CMD_SYNC, (uint32_t)&wifiCb, 0);
+ Request();
+
+ // empty the response queue hoping to find the wifiCb address
+ STMClientPacket *packet;
+ while ((packet = WaitReturn(timeout)) != NULL) {
+ if (packet->value == (uint32_t)&wifiCb)
+ {
+ // _debug->printf("SYNC!");
+ // wait(0.5);
+ return true;
+ }
+ _debug->printf("BAD: %s /n/r", packet->value);
+ }
+
+ // doesn't look like we got a real response
+ return false;
+}
+
+void STMClient::GetWifiStatus(void) {
+ Request(CMD_WIFI_STATUS, 0, 0);
+ Request();
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/STMClient.h Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,116 @@
+#ifndef _STM_CLIENT_H_
+#define _STM_CLIENT_H_
+
+#include "mbed.h"
+#include "STMClientResponse.h"
+#include "FP.h"
+
+#define ESP_TIMEOUT 2000
+
+// Enumeration of commands supported by esp-link, this needs to match the definition in
+// esp-link!
+typedef enum {
+ CMD_NULL = 0, // null, mainly to prevent 0 from doing something bad
+ CMD_SYNC, // synchronize, starts the protocol
+ CMD_RESP_V, // response with a value
+ CMD_RESP_CB, // response with a callback
+ CMD_WIFI_STATUS, // get the wifi status
+ CMD_CB_ADD, // add a custom callback
+ CMD_CB_EVENTS, // ???
+ CMD_GET_TIME, // get current time in seconds since the unix epoch
+ //CMD_GET_INFO,
+
+ CMD_MQTT_SETUP = 10,
+ CMD_MQTT_PUBLISH,
+ CMD_MQTT_SUBSCRIBE,
+ CMD_MQTT_LWT,
+ CMD_MQTT_EVENTS,
+
+ CMD_REST_SETUP = 20,
+ CMD_REST_REQUEST,
+ CMD_REST_SETHEADER,
+ CMD_REST_EVENTS
+
+} CmdName;
+
+enum WIFI_STATUS {
+ STATION_IDLE = 0,
+ STATION_CONNECTING,
+ STATION_WRONG_PASSWORD,
+ STATION_NO_AP_FOUND,
+ STATION_CONNECT_FAIL,
+ STATION_GOT_IP
+};
+
+typedef struct {
+ uint8_t* buf;
+ uint16_t bufSize;
+ uint16_t dataLen;
+ uint8_t isEsc;
+} STMClientProtocol;
+
+class STMClient {
+ public:
+ //Make the serial process interrupt driven
+
+ // Create an esp-link client based on a stream and with a specified debug output stream.
+ STMClient(Serial* serial, Serial* debug);
+
+ // Create an esp-link client based on a stream with no debug output
+ STMClient(Serial* serial);
+
+ Serial* _debug;
+
+ //== Requests
+ // Start a request. cmd is the command to execute, value is either the address of a function
+ // to call with a response or a first argument to the command if there is no CB.
+ // Argc is the number of additional arguments
+ void Request(uint16_t cmd, uint32_t value, uint16_t argc);
+
+ // Add a data block as argument to a request
+ void Request(const void* data, uint16_t len);
+
+ // Add a data block from flash as argument to a request
+ //void Request(const __FlashStringHelper* data, uint16_t len); //commented out for now...
+
+ // Finish a request
+ void Request(void);
+
+ //== Responses
+ // Process the input stream, call this in loop() to dispatch call-back based responses.
+ // Callbacks are invoked with an STMClientResponse pointer as argument.
+ // Returns the STMClientPacket if a non-callback response was received, typically this is
+ // used to create an STMClientResponse. Returns NULL if no response needs to be processed.
+ STMClientPacket *Process(void);
+
+ // Busy wait for a response with a timeout in milliseconds, returns an STMClientPacket
+ // if a response was recv'd and NULL otherwise. The STMClientPacket is typically used to
+ // create an STMClientResponse.
+ STMClientPacket *WaitReturn(uint32_t timeout=ESP_TIMEOUT);
+
+ //== Commands built-into STMClient
+ // Initialize and synchronize communication with esp-link with a timeout in milliseconds,
+ // and remove all existing callbacks. Registers the wifiCb and returns true on success
+ bool Sync(uint32_t timeout=ESP_TIMEOUT);
+ // Request the wifi status
+ void GetWifiStatus(void);
+
+ // Callback for wifi status changes that must be attached before calling Sync
+ FP<void, void*> wifiCb;
+
+ //private:
+ Serial* _serial;
+ bool _debugEn;
+ uint16_t crc;
+ STMClientProtocol _proto;
+ uint8_t _protoBuf[128];
+
+ void init();
+ void DBG(const char* info);
+ STMClientPacket *protoCompletedCb(void);
+ void write(uint8_t data);
+ void write(void* data, uint16_t len);
+ uint16_t crc16Add(unsigned char b, uint16_t acc);
+ uint16_t crc16Data(const unsigned char *data, uint16_t len, uint16_t acc);
+};
+#endif // _EL_CLIENT_H_
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/STMClientCmd.cpp Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,12 @@
+
+#include "STMClientCmd.h"
+
+STMClientCmd::STMClientCmd(STMClient* elc) :_elc(elc) {}
+
+uint32_t STMClientCmd::GetTime() {
+ _elc->Request(CMD_GET_TIME, 0, 0);
+ _elc->Request();
+
+ STMClientPacket *pkt = _elc->WaitReturn();
+ return pkt ? pkt->value : 0;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/STMClientCmd.h Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,19 @@
+// MiscSTMlaneous commands
+
+#ifndef _STM_CLIENT_CMD_H_
+#define _STM_CLIENT_CMD_H_
+
+#include "STMClient.h"
+#include "FP.h"
+
+class STMClientCmd {
+ public:
+ // Constructor
+ STMClientCmd(STMClient* elc);
+ // Get the current time in seconds since the epoch, 0 if the time is unknown
+ uint32_t GetTime();
+
+ private:
+ STMClient* _elc;
+};
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/STMClientResponse.cpp Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,87 @@
+#include "STMClientResponse.h"
+
+STMClientResponse::STMClientResponse(STMClientPacket* packet) {
+ _cmd = packet;
+ _arg_ptr = _cmd->args;
+ _arg_num = 0;
+}
+
+STMClientResponse::STMClientResponse(void* packet) {
+ _cmd = (STMClientPacket *)packet;
+ _arg_ptr = _cmd->args;
+ _arg_num = 0;
+}
+
+int16_t STMClientResponse::popArgPtr(void **data) {
+ if (_arg_num >= _cmd->argc) return -1;
+
+ uint16_t len = *(uint16_t*)_arg_ptr;
+ uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length
+ _arg_ptr += 2;
+ _arg_num++;
+
+ *data = _arg_ptr;
+ _arg_ptr += len + pad;
+ return len;
+}
+
+int16_t STMClientResponse::popArg(void* d, uint16_t maxLen) {
+ if (_arg_num >= _cmd->argc) return -1;
+
+ uint16_t len = *(uint16_t*)_arg_ptr;
+ uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length
+ _arg_ptr += 2;
+ _arg_num++;
+
+ uint8_t *data = (uint8_t *)d;
+ uint16_t l = len > maxLen ? maxLen : len;
+ uint8_t *p = _arg_ptr;
+ while (l--)
+ *data++ = *p++;
+
+ _arg_ptr += len + pad;
+ return len;
+}
+
+void STMClientResponse::popChar(char* buffer) {
+ uint16_t len = *(uint16_t*)_arg_ptr;
+ uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length
+ _arg_ptr += 2;
+ _arg_num++;
+
+ uint8_t i;
+ for (i = 0; i < len; i++) {
+ buffer[i] = (char)*_arg_ptr++;
+ }
+ buffer[i] = '\0';
+
+ _arg_ptr += pad;
+}
+
+string STMClientResponse::popString() {
+ string ret;
+ uint16_t len = *(uint16_t*)_arg_ptr;
+ uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length
+ _arg_ptr += 2;
+ _arg_num++;
+
+ while (len--)
+ ret += (char)*_arg_ptr++;
+
+ _arg_ptr += pad;
+ return ret;
+}
+
+void STMClientResponse::popString(string* data) {
+ uint16_t len = *(uint16_t*)_arg_ptr;
+ uint16_t pad = (4-((len+2)&3))&3; // pad to next multiple of 4, including length
+ _arg_ptr += 2;
+ _arg_num++;
+
+ while (len--)
+ //string.append((char)*_arg_ptr++);
+ //strcat (data,(char)*_arg_ptr++);
+ data += (char)*_arg_ptr++;
+
+ _arg_ptr += pad;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/STMClientResponse.h Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,52 @@
+#ifndef _STM_CLIENT_RESPONSE_H_
+#define _STM_CLIENT_RESPONSE_H_
+
+#if _MSC_VER
+#define PACKED
+#else
+#define PACKED __attribute__ ((__packed__))
+#endif
+
+#include <mbed.h>
+#include <string>
+
+typedef struct PACKED {
+ uint16_t cmd; // command to execute
+ uint16_t argc; // number of arguments
+ uint32_t value; // callback to invoke, NULL if none; or response value
+ uint8_t args[0];
+} STMClientPacket;
+
+class STMClientResponse {
+ public:
+ // Create a response from a packet, this is done internally in STMClient
+ STMClientResponse(STMClientPacket* packet);
+ STMClientResponse(void *packet);
+
+ // Accessors to the response fields
+ uint16_t argc() { return _cmd->argc; }
+ uint16_t cmd() { return _cmd->cmd; }
+ uint32_t value() { return _cmd->value; }
+
+ // Return the length of the next argument
+ uint16_t argLen() { return *(uint16_t*)_arg_ptr; }
+ // Pop one argument from the response, returns the actual length. Returns -1 if there is
+ // no arg left.
+ int16_t popArg(void* data, uint16_t maxLen);
+ // Pop one argument as a poiner from the response, returns the actual length.
+ int16_t popArgPtr(void **data);
+ // Pop one argument into a string buffer and append a null character. The buffer needs to
+ // be large enough (argLen()+1)
+ void popChar(char* buffer);
+ // Pop one argument into a String buffer
+ string popString();
+ // Pop one argument into a String buffer
+ void popString(string* data);
+
+ private:
+ uint16_t _arg_num;
+ uint8_t* _arg_ptr;
+ STMClientPacket* _cmd;
+};
+
+#endif // _STM_CLIENT_RESPONSE_H_
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/STMClientRest.cpp Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,115 @@
+#include "STMClientRest.h"
+#include "millis.h"
+
+typedef enum {
+ HEADER_GENERIC = 0,
+ HEADER_CONTENT_TYPE,
+ HEADER_USER_AGENT
+} HEADER_TYPE;
+
+STMClientRest::STMClientRest(STMClient *e)
+{
+ _elc = e;
+ remote_instance = -1;
+}
+
+void STMClientRest::restCallback(void *res)
+{
+ if (!res) return;
+
+ STMClientResponse *resp = (STMClientResponse *)res;
+
+ resp->popArg(&_status, sizeof(_status));
+ _elc->_debug->printf("REST code %i \n\r",_status);
+
+ _len = resp->popArgPtr(&_data);
+}
+
+int STMClientRest::begin(const char* host, uint16_t port, bool security)
+{
+ uint8_t sec = !!security;
+ restCb.attach(this, &STMClientRest::restCallback);
+
+ _elc->Request(CMD_REST_SETUP, (uint32_t)&restCb, 3);
+ _elc->Request(host, strlen(host));
+ _elc->Request(&port, 2);
+ _elc->Request(&sec, 1);
+ _elc->Request();
+
+ STMClientPacket *pkt = _elc->WaitReturn();
+ if (pkt && (int32_t)pkt->value >= 0) {
+ remote_instance = pkt->value;
+ return 0;
+ }
+ return (int)pkt->value;
+}
+
+void STMClientRest::request(const char* path, const char* method, const char* data, int len)
+{
+ _status = 0;
+ if (remote_instance < 0) return;
+ if (data != 0 && len > 0) _elc->Request(CMD_REST_REQUEST, remote_instance, 3);
+ else _elc->Request(CMD_REST_REQUEST, remote_instance, 2);
+ _elc->Request(method, strlen(method));
+ _elc->Request(path, strlen(path));
+ if (data != NULL && len > 0) {
+ _elc->Request(data, len);
+ }
+
+ _elc->Request();
+}
+
+void STMClientRest::request(const char* path, const char* method, const char* data)
+{
+ request(path, method, data, strlen(data));
+}
+
+void STMClientRest::get(const char* path, const char* data) { request(path, "GET", data); }
+void STMClientRest::post(const char* path, const char* data) { request(path, "POST", data); }
+void STMClientRest::put(const char* path, const char* data) { request(path, "PUT", data); }
+void STMClientRest::del(const char* path) { request(path, "DELETE", 0); }
+
+void STMClientRest::setHeader(const char* value)
+{
+ uint8_t header_index = HEADER_GENERIC;
+ _elc->Request(CMD_REST_SETHEADER, remote_instance, 2);
+ _elc->Request(&header_index, 1);
+ _elc->Request(value, strlen(value));
+ _elc->Request();
+}
+
+void STMClientRest::setContentType(const char* value)
+{
+ uint8_t header_index = HEADER_CONTENT_TYPE;
+ _elc->Request(CMD_REST_SETHEADER, remote_instance, 2);
+ _elc->Request(&header_index, 1);
+ _elc->Request(value, strlen(value));
+ _elc->Request();
+}
+
+void STMClientRest::setUserAgent(const char* value)
+{
+ uint8_t header_index = HEADER_USER_AGENT;
+ _elc->Request(CMD_REST_SETHEADER, remote_instance, 2);
+ _elc->Request(&header_index, 1);
+ _elc->Request(value, strlen(value));
+ _elc->Request();
+}
+
+uint16_t STMClientRest::getResponse(char* data, uint16_t maxLen)
+{
+ if (_status == 0) return 0;
+ memcpy(data, _data, _len>maxLen?maxLen:_len);
+ int16_t s = _status;
+ _status = 0;
+ return s;
+}
+
+uint16_t STMClientRest::waitResponse(char* data, uint16_t maxLen, uint32_t timeout)
+{
+ uint32_t wait = millis();
+ while (_status == 0 && (millis() - wait < timeout)) {
+ _elc->Process();
+ }
+ return getResponse(data, maxLen);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/STMClientRest.h Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,88 @@
+
+#ifndef _STM_CLIENT_REST_H_
+#define _STM_CLIENT_REST_H_
+
+#include "FP.h"
+#include "STMClient.h"
+
+// Default timeout for REST requests when waiting for a response
+#define DEFAULT_REST_TIMEOUT 5000
+
+typedef enum {
+ HTTP_STATUS_OK = 200
+} HTTP_STATUS;
+
+// The STMClientRest class makes simple REST requests to a remote server. Each instance
+// is used to communicate with one server and multiple instances can be created to make
+// requests to multiple servers.
+// The STMClientRest class does not support concurrent requests to the same server because
+// only a single response can be recevied at a time and the responses of the two requests
+// may arrive out of order.
+// A major limitation of the REST class is that it does not store the response body. The
+// response status is saved in the class instance, so after a request completes and before
+// the next request is made a call to getResponse will return the status. However, only a pointer
+// to the response body is saved, which means that if any other message arrives and is
+// processed then the response body is overwritten by it. What this means is that if you
+// need the response body you best use waitResponse or ensure that any call to STMClient::process
+// is followed by a call to getResponse. Ideally someone improves this class to take a callback
+// into the user's sketch?
+// Another limitation is that the response body is 100 chars long at most, this is due to the
+// limitation of the SLIP protocol buffer available.
+class STMClientRest {
+ public:
+ STMClientRest(STMClient *e);
+
+ // Initialize communication to a remote server, this communicates with esp-link but does not
+ // open a connection to the remote server. Host may be a hostname or an IP address,
+ // security causes HTTPS to be used (not yet supported). Returns 0 if the set-up is
+ // successful, returns a negative error code if it failed.
+ int begin(const char* host, uint16_t port=80, bool security=false);
+
+ // Make a request to the remote server. The data must be null-terminated
+ void request(const char* path, const char* method, const char* data=NULL);
+
+ // Make a request to the remote server.
+ void request(const char* path, const char* method, const char* data, int len);
+
+ // Make a GET request to the remote server with NULL-terminated data
+ void get(const char* path, const char* data=NULL);
+
+ // Make a POST request to the remote server with NULL-terminated data
+ void post(const char* path, const char* data);
+
+ // Make a PUT request to the remote server with NULL-terminated data
+ void put(const char* path, const char* data);
+
+ // Make a DELETE request to the remote server
+ void del(const char* path);
+
+ // Retrieve the response from the remote server, returns the HTTP status code, 0 if no
+ // response (may need to wait longer)
+ uint16_t getResponse(char* data, uint16_t maxLen);
+
+ // Wait for the response from the remote server, returns the HTTP status code, 0 if no
+ // response (timeout occurred)
+ uint16_t waitResponse(char* data, uint16_t maxLen, uint32_t timeout=DEFAULT_REST_TIMEOUT);
+
+ // Set the user-agent for all subsequent requests
+ void setUserAgent(const char* value);
+
+ // Set the Content-Type Header for all subsequent requests
+ void setContentType(const char* value);
+
+ // Set a custom header for all subsequent requests
+ void setHeader(const char* value);
+
+ private:
+ int32_t remote_instance;
+ STMClient *_elc;
+ void restCallback(void* resp);
+ FP<void, void*> restCb;
+
+ int16_t _status;
+ uint16_t _len;
+ void *_data;
+
+
+};
+#endif // _STM_CLIENT_REST_H_
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/library.json Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,16 @@
+{
+ "name": "STMClient",
+ "keywords": "wifi, mqtt, rest",
+ "description": "Wifi library (Chip ESP8266 Wifi SoC) using SLIP protocol via Serial port",
+ "url": "https://github.com/",
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/"
+ },
+ "include": "STMClient",
+ "frameworks": "STM32-F446RE",
+ "platforms": [
+ "Nucleo"
+ ]
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,139 @@
+/**
+ * Simple example to demo the STM-Client REST calls
+ */
+#include "mbed.h"
+#include <STMClient.h>
+#include <STMClientRest.h>
+
+/*-------- Check if platform compatible ----------*/
+#if DEVICE_SERIAL_ASYNCH
+Serial debugSerial(SERIAL_TX, SERIAL_RX);
+Serial espSerial(PA_0, PA_1);
+#else
+ #warning "Platform not compatible with Low Power APIs for Serial"
+ Serial debugSerial(SERIAL_TX, SERIAL_RX);
+ Serial espSerial(PA_0, PA_1);
+#endif
+
+
+DigitalOut led1(LED1);
+
+// Initialize a connection to esp-link using the normal hardware serial port both for
+// SLIP and for debug messages.
+STMClient esp(&espSerial, &debugSerial);
+
+
+// Initialize a REST client on the connection to esp-link
+STMClientRest rest(&esp);
+
+bool wifiConnected = false;
+
+// Callback made from esp-link to notify of wifi status changes
+// Here we print something out and set a global flag
+void wifiCb(void *response) {
+ debugSerial.printf("waiting for wifi status...\n\r"); //debug
+ STMClientResponse *res = (STMClientResponse*)response;
+ if (res->argc() == 1) {
+ uint8_t status;
+ res->popArg(&status, 1);
+ debugSerial.printf("waiting for wifi status...\n\r");
+ if(status == STATION_GOT_IP) {
+ debugSerial.printf("WIFI CONNECTED");
+ wifiConnected = true;
+ } else {
+ debugSerial.printf("WIFI NOT READY: %i",status);
+ //Serial.printf(status);
+ wifiConnected = false;
+ }
+ }
+}
+
+#define BUFLEN 266
+
+int loop() {
+ //debugSerial.printf("begin main loop \n\r");
+ // process any callbacks coming from esp_link
+ esp.Process();
+ debugSerial.printf("Wifi Connected: %i \n\r",wifiConnected);
+ // if we're connected make an HTTP request
+ while(wifiConnected) {
+ // Request /utc/now from the previously set-up server
+ rest.get("/utc/now");
+
+ char response[BUFLEN];
+ memset(response, 0, BUFLEN);
+ uint16_t code = rest.waitResponse(response, BUFLEN);
+ if(code == HTTP_STATUS_OK){
+ debugSerial.printf("STM: GET successful: %s\n\r", response);
+ } else {
+ debugSerial.printf("STM: GET failed: %i\n\r",code);
+ return code;
+ }
+ wait(1);
+ }
+ return 0;
+
+}
+
+int main() {
+ led1=0;
+ debugSerial.baud(115200); // the baud rate here needs to match the esp-link config
+ espSerial.baud(115200);
+
+ debugSerial.printf("STM-Client starting!\n\r");
+ wait(0.5);
+
+ espSerial.printf("STM-Client starting!\n\r");
+ wait(0.5);
+
+ // Sync-up with esp-link, this is required at the start of any sketch and initializes the
+ // callbacks to the wifi status change callback. The callback gets called with the initial
+ // status right after Sync() below completes.
+ esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired)
+ bool ok;
+ do {
+ //debugSerial.printf("main syncing..\n\r");
+ wait(0.5);
+ ok = esp.Sync(); // sync up with esp-link, blocks for up to 2 seconds
+ if (!ok){
+ debugSerial.printf("STM-Client sync failed!\n\r");
+ wait(0.5);
+ }
+ } while(!ok);
+
+ debugSerial.printf("STM-Client synced!\n\r");
+
+ // Get immediate wifi status info for demo purposes. This is not normally used because the
+ // wifi status callback registered above gets called immediately.
+ esp.GetWifiStatus();
+ STMClientPacket *packet;
+ if ((packet=esp.WaitReturn()) != NULL)
+ {
+ //debugSerial.printf("Wifi status: %i\n\r", packet->value);
+ //debugSerial.printf("waiting for wifi status...\n\r");
+ if(packet->value == 2) { ///ideally this would coincide with STATION_GOT_IP...
+ debugSerial.printf("WIFI CONNECTED\n\r");
+ wifiConnected = true;
+ } else {
+ debugSerial.printf("WIFI NOT READY: %i\n\r",packet->value);
+ //Serial.printf(status);
+ wifiConnected = false;
+ }
+ }
+
+
+ // Set up the REST client to talk to www.timeapi.org, this doesn't connect to that server,
+ // it just sets-up stuff on the esp-link side
+ int err = rest.begin("www.timeapi.org");
+ if (err != 0) {
+ debugSerial.printf("REST begin failed: %i\n\r",err);
+ while(1) ;
+ }
+ debugSerial.printf("STM-REST ready\n\r");
+ int loopStat = 0;
+ while(loopStat == 0){
+ debugSerial.printf("status: %i\n\r",loopStat);
+ loopStat = loop();
+ wait(1);
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Jul 14 20:38:18 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/6c34061e7c34 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/millis.cpp Thu Jul 14 20:38:18 2016 +0000
@@ -0,0 +1,16 @@
+#include "mbed.h"
+#include "millis.h"
+
+volatile unsigned long _millis;
+
+void millisStart(void) {
+ SysTick_Config(SystemCoreClock / 1000);
+}
+
+extern "C" void SysTick_Handler(void) {
+ _millis++;
+}
+
+unsigned long millis(void) {
+ return _millis;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/millis.h Thu Jul 14 20:38:18 2016 +0000 @@ -0,0 +1,7 @@ +#ifndef MILLIS_H +#define MILLIS_H + +void millisStart(void); +unsigned long millis(void); + +#endif \ No newline at end of file