@@ -27,6 +27,10 @@ type Board struct {
27
27
BoardID string
28
28
Properties * properties.Map `json:"-"`
29
29
PlatformRelease * PlatformRelease `json:"-"`
30
+ configOptions * properties.Map
31
+ configOptionValues map [string ]* properties.Map
32
+ configOptionProperties map [string ]* properties.Map
33
+ defaultConfig * properties.Map
30
34
identificationProperties []* properties.Map
31
35
}
32
36
@@ -64,66 +68,74 @@ func (b *Board) String() string {
64
68
return b .FQBN ()
65
69
}
66
70
71
+ func (b * Board ) buildConfigOptionsStructures () {
72
+ if b .configOptions != nil {
73
+ return
74
+ }
75
+
76
+ b .configOptions = properties .NewMap ()
77
+ allConfigs := b .Properties .SubTree ("menu" )
78
+ for _ , option := range allConfigs .FirstLevelKeys () {
79
+ b .configOptions .Set (option , b .PlatformRelease .Menus .Get (option ))
80
+ }
81
+
82
+ b .configOptionValues = map [string ]* properties.Map {}
83
+ b .configOptionProperties = map [string ]* properties.Map {}
84
+ b .defaultConfig = properties .NewMap ()
85
+ for option , optionProps := range allConfigs .FirstLevelOf () {
86
+ b .configOptionValues [option ] = properties .NewMap ()
87
+ values := optionProps .FirstLevelKeys ()
88
+ b .defaultConfig .Set (option , values [0 ])
89
+ for _ , value := range values {
90
+ if label , ok := optionProps .GetOk (value ); ok {
91
+ b .configOptionValues [option ].Set (value , label )
92
+ b .configOptionProperties [option + "=" + value ] = optionProps .SubTree (value )
93
+ }
94
+ }
95
+ }
96
+ }
97
+
67
98
// GetConfigOptions returns an OrderedMap of configuration options for this board.
68
99
// The returned map will have key and value as option id and option name, respectively.
69
100
func (b * Board ) GetConfigOptions () * properties.Map {
70
- res := properties .NewMap ()
71
- menu := b .Properties .SubTree ("menu" )
72
- for _ , option := range menu .FirstLevelKeys () {
73
- res .Set (option , b .PlatformRelease .Menus .Get (option ))
74
- }
75
- return res
101
+ b .buildConfigOptionsStructures ()
102
+ return b .configOptions
76
103
}
77
104
78
105
// GetConfigOptionValues returns an OrderedMap of possible values for a specific configuratio options
79
106
// for this board. The returned map will have key and value as option value and option value name,
80
107
// respectively.
81
108
func (b * Board ) GetConfigOptionValues (option string ) * properties.Map {
82
- res := properties .NewMap ()
83
- menu := b .Properties .SubTree ("menu" ).SubTree (option )
84
- for _ , value := range menu .FirstLevelKeys () {
85
- if label , ok := menu .GetOk (value ); ok {
86
- res .Set (value , label )
87
- }
88
- }
89
- return res
109
+ b .buildConfigOptionsStructures ()
110
+ return b .configOptionValues [option ]
90
111
}
91
112
92
113
// GetBuildProperties returns the build properties and the build
93
114
// platform for the Board with the configuration passed as parameter.
94
115
func (b * Board ) GetBuildProperties (userConfigs * properties.Map ) (* properties.Map , error ) {
95
- // Clone user configs because they are destroyed during iteration
96
- userConfigs = userConfigs .Clone ()
116
+ b .buildConfigOptionsStructures ()
117
+
118
+ // Override default configs with user configs
119
+ config := b .defaultConfig .Clone ()
120
+ config .Merge (userConfigs )
97
121
98
122
// Start with board's base properties
99
123
buildProperties := b .Properties .Clone ()
100
124
101
125
// Add all sub-configurations one by one (a config is: option=value)
102
- menu := b .Properties .SubTree ("menu" )
103
- for _ , option := range menu .FirstLevelKeys () {
104
- optionMenu := menu .SubTree (option )
105
- userValue , haveUserValue := userConfigs .GetOk (option )
106
- if haveUserValue {
107
- userConfigs .Remove (option )
108
- if ! optionMenu .ContainsKey (userValue ) {
109
- return nil , fmt .Errorf (tr ("invalid value '%[1]s' for option '%[2]s'" ), userValue , option )
110
- }
111
- } else {
112
- // apply default
113
- userValue = optionMenu .FirstLevelKeys ()[0 ]
114
- }
115
-
116
- optionsConf := optionMenu .SubTree (userValue )
117
- buildProperties .Merge (optionsConf )
118
- }
119
-
120
126
// Check for residual invalid options...
121
- if invalidKeys := userConfigs .Keys (); len (invalidKeys ) > 0 {
122
- invalidOption := invalidKeys [0 ]
123
- if invalidOption == "" {
127
+ for option , value := range config .AsMap () {
128
+ if option == "" {
124
129
return nil , fmt .Errorf (tr ("invalid empty option found" ))
125
130
}
126
- return nil , fmt .Errorf (tr ("invalid option '%s'" ), invalidOption )
131
+ if _ , ok := b .configOptions .GetOk (option ); ! ok {
132
+ return nil , fmt .Errorf (tr ("invalid option '%s'" ), option )
133
+ }
134
+ optionsConf , ok := b .configOptionProperties [option + "=" + value ]
135
+ if ! ok {
136
+ return nil , fmt .Errorf (tr ("invalid value '%[1]s' for option '%[2]s'" ), value , option )
137
+ }
138
+ buildProperties .Merge (optionsConf )
127
139
}
128
140
129
141
return buildProperties , nil
@@ -153,7 +165,7 @@ func (b *Board) GetIdentificationProperties() []*properties.Map {
153
165
}
154
166
155
167
// IsBoardMatchingIDProperties returns true if the board match the given
156
- // identification properties
168
+ // upload port identification properties
157
169
func (b * Board ) IsBoardMatchingIDProperties (query * properties.Map ) bool {
158
170
// check checks if the given set of properties p match the "query"
159
171
check := func (p * properties.Map ) bool {
@@ -179,3 +191,40 @@ func (b *Board) IsBoardMatchingIDProperties(query *properties.Map) bool {
179
191
func GetMonitorSettings (protocol string , boardProperties * properties.Map ) * properties.Map {
180
192
return boardProperties .SubTree ("monitor_port." + protocol )
181
193
}
194
+
195
+ // IdentifyBoardConfiguration returns the configuration of the board that can be
196
+ // deduced from the given upload port identification properties
197
+ func (b * Board ) IdentifyBoardConfiguration (query * properties.Map ) * properties.Map {
198
+ // check checks if the given set of properties p match the "query"
199
+ check := func (p * properties.Map ) bool {
200
+ for k , v := range p .AsMap () {
201
+ if ! strings .EqualFold (query .Get (k ), v ) {
202
+ return false
203
+ }
204
+ }
205
+ return true
206
+ }
207
+ checkAll := func (allP []* properties.Map ) bool {
208
+ for _ , p := range allP {
209
+ if check (p ) {
210
+ return true
211
+ }
212
+ }
213
+ return false
214
+ }
215
+
216
+ res := properties .NewMap ()
217
+ for _ , option := range b .GetConfigOptions ().Keys () {
218
+ values := b .GetConfigOptionValues (option ).Keys ()
219
+
220
+ for _ , value := range values {
221
+ config := option + "=" + value
222
+ configProps := b .configOptionProperties [config ]
223
+
224
+ if checkAll (configProps .ExtractSubIndexSets ("upload_port" )) {
225
+ res .Set (option , value )
226
+ }
227
+ }
228
+ }
229
+ return res
230
+ }
0 commit comments