Index: trunk/psModules/src/concepts/pmConceptsStandard.c
===================================================================
--- trunk/psModules/src/concepts/pmConceptsStandard.c	(revision 25425)
+++ trunk/psModules/src/concepts/pmConceptsStandard.c	(revision 25882)
@@ -4,6 +4,7 @@
 
 #include <stdio.h>
+#include <ctype.h>			// for tolower()
 #include <string.h>
-#include <strings.h>            /* for strn?casecmp */
+#include <strings.h>			// for strn?casecmp 
 #include <assert.h>
 #include <pslib.h>
@@ -317,4 +318,107 @@
             "Unable to find %s in FILTER.ID in camera configuration.\n", key);
     return NULL;
+}
+
+// FPA.OBSTYPE
+// convert concept->data.str to new value 
+psMetadataItem *p_pmConceptParse_FPA_OBSTYPE(const psMetadataItem *concept,
+                                            const psMetadataItem *pattern,
+                                            pmConceptSource source,
+                                            const psMetadata *cameraFormat,
+                                            const pmFPA *fpa,
+                                            const pmChip *chip,
+                                            const pmCell *cell)
+{
+    assert(concept);
+    assert(pattern);
+    assert(fpa);
+    assert(fpa->camera);
+
+    if (concept->type != PS_DATA_STRING) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for %s (%x) is not STR\n",
+                pattern->name, concept->type);
+        return NULL;
+    }
+    if (!concept->data.str || strlen(concept->data.str) == 0) {
+        return psMetadataItemAllocStr(pattern->name, pattern->comment, "");
+    }
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *table = psMetadataLookupMetadata(&mdok, fpa->camera, "OBSTYPE.TABLE");
+    if (!mdok || !table) {
+	// if the table is not defined, pass the supplied value unmodified
+        return psMetadataItemAllocStr(pattern->name, pattern->comment, concept->data.str);
+    }
+
+    // the metadata is in the format (external) STR (internal) 
+    // do a lookup to get the internal name
+    char *extname = psStringCopy (concept->data.str);
+    for (int i = 0; i < strlen(extname); i++) {
+	extname[i] = tolower(extname[i]);
+    }
+    char *name = psMetadataLookupStr (&mdok, table, extname);
+    psFree(extname);
+    if (!name) {
+	// if the entry is not defined, pass the supplied value unmodified
+        return psMetadataItemAllocStr(pattern->name, pattern->comment, concept->data.str);
+    }
+
+    return psMetadataItemAllocStr(pattern->name, pattern->comment, name);
+}
+
+// convert concept->data.str to new value 
+psMetadataItem *p_pmConceptFormat_FPA_OBSTYPE(const psMetadataItem *concept,
+                                             pmConceptSource source,
+                                             const psMetadata *cameraFormat,
+                                             const pmFPA *fpa,
+                                             const pmChip *chip,
+                                             const pmCell *cell)
+{
+    assert(concept);
+    assert(fpa);
+    assert(fpa->camera);
+
+    if (concept->type != PS_DATA_STRING) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for %s (%x) is not STR\n",
+                concept->name, concept->type);
+        return NULL;
+    }
+    if (!concept->data.str || strlen(concept->data.str) == 0) {
+        return psMetadataItemAllocStr(concept->name, concept->comment, "");
+    }
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *table = psMetadataLookupMetadata(&mdok, fpa->camera, "OBSTYPE.TABLE");
+    if (!mdok || !table) {
+	// if the table is not defined, pass the supplied value unmodified
+        return psMetadataItemAllocStr(concept->name, concept->comment, concept->data.str);
+    }
+
+    const char *key = concept->data.str;        // The name to look up
+    if (!key || strlen(key) == 0) {
+        return psMetadataItemAllocStr(concept->name, concept->comment, NULL);
+    }
+
+    // the metadata is in the format (internal) STR (external)
+    // do a reverse lookup to get the internal name
+    psMetadataIterator *iter = psMetadataIteratorAlloc(table, PS_LIST_HEAD, NULL); // Iterator for filters
+    psMetadataItem *item;               // Item from iteration
+    char *name = NULL;                  // The winning name
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (item->type != PS_DATA_STRING) {
+            psWarning("Type for %s (%x) in OBSTYPE.TABLE in camera configuration is not STR\n", item->name, item->type);
+            continue;
+        }
+        if (strcmp(item->data.str, key) == 0) {
+            name = item->name;
+            break;
+        }
+    }
+    psFree(iter);
+
+    if (!name) {
+	return psMetadataItemAllocStr(concept->name, concept->comment, key);
+    }
+    return psMetadataItemAllocStr(concept->name, concept->comment, name);
 }
 
